1.handler,looper,messagequeue三者之间的关系以及各自的角色?

答:MessageQueue就是存储消息的载体,Looper就是无限循环查找这个载体里是否还有消息。Handler就是创建的时候 会使用looper来构建这个消息循环。

handler的主要功能就是 将一个任务切换到某个指定的线程中去执行。

2.为何android 无法在子线程更新ui?

答:都知道 更新ui 实际工作都是在viewrootimpl这个类里面去做的。他的源码里有下面这样一个函数:

   void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}

在源码里 就限定了 你这个子线程是不能访问ui的。只有主线程能访问ui。原因其实很简单,你要是允许子线程也操作ui,那就得给ui 加上锁机制,

锁机制就太影响效率了。所以为了效率 就控制开发者 只能在主线程上访问ui。

3.简单概述一下Handler的工作原理?

答:其实很简单,关系理顺了就可以了。首先要明白 handler要创建成功 必须有一个前提条件 就是创建handler的线程 必须有looper。不然就会报错。

  handler使用方法 一般就2个 post 传一个runnable 或者send一个消息。注意的是post方法 最后其实也是调用的send方法。这个send方法

  最终会调用messagequeue的enqueuemessage方法,就是把消息放入队列中。与此同时looper 是一个无限循环 会无限从这个消息队列里面

取消息,取出来以后 消息中的runnable 或者 handler的handlerMessage方法就会被调用了。这个地方有一个关键的地方就在于 我们的looper

是运行在 创建handler的线程中的。所以looper在处理消息的时候 会把这个消息也运行在 创建handler的所在线程中。想明白这点 就明白了

  handler的运行机制了。

4.简单介绍下threadLocal?

答:这个东西 在looper activitythread 以及ams中 都有大量应用。其实作用就是在指定的线程中存储数据。当你希望有一个数据 在不同线程中 都能独立保存自己的独立值

互相不干扰互相不影响的时候 就可以使用threadlocal了。他的作用域仅限于线程。

给个例子

 package com.example;

 public class MyClass {

     public static void main(String[] args) {

         ThreadLocal<Integer> mIntegerThreadLocal = new ThreadLocal<Integer>();
mIntegerThreadLocal.set(0);
//输出结果为main thread threadlocal==0
System.out.println("main thread threadlocal==" + mIntegerThreadLocal.get()); new Thread("Thread 1") {
@Override
public void run() {
mIntegerThreadLocal.set(0);
mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
//输出结果为 Thread 1 threadlocal==2
System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
}
}.start(); new Thread("Thread 2") {
@Override
public void run() {
//这里就会报空指针错误了 因为mIntegerThreadLocal 在这个线程中没有初始化他的值所以是null pointer
mIntegerThreadLocal.set(mIntegerThreadLocal.get() + 2);
System.out.println("Thread 1 threadlocal==" + mIntegerThreadLocal.get());
}
}.start(); }
}

5.从源码的角度 阐述threadlocal的原理?

答:

 //首先我们可以看到 这是一个泛型, 我们的分析 建立在java 1.8 的基础上 其他java版本这里实现都有各自的不同 有兴趣的可以自己自行分析
public class ThreadLocal<T> { //然后我们看一下 set方法
public void set(T value) {
//先取出当前的thread
Thread t = Thread.currentThread();
//然后从getMap方法里 取t 也就是当前这个thread的数据 , ThreadLocalMap是一个静态内部类 你可以把他看做 存储threadlocal数据的一个载体
ThreadLocalMap map = getMap(t);
//如果取出来是空 那就给他set一个值进去 也就是更新这个threadlocal的值
if (map != null)
map.set(this, value);
else
//否则就创建一个ThreadLocalMap的值
createMap(t, value);
} //getMap就是取出这个线程的threadLocals 如果这个值为null 就说明这个线程还从来没有使用过threadlocal对象
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
} //我们可以先跟踪createMap方法 也就是创建ThreadLocalMap的流程
void createMap(Thread t, T firstValue) {
//这里thread的threadLocals 的值 就是在这里被赋值了,也就是ThreadLocalMap对象
//可以明确 一个线程T,就有一个唯一的ThreadLocalMap对象,里面存储的就是
//这个线程里的th对象。也就是threadlocal
t.threadLocals = new ThreadLocalMap(this, firstValue);
} //可以看到是用这个构造方法来构造的
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
//首先是创造了一个table数组
table = new Entry[INITIAL_CAPACITY];
//然后根据一定的算法 计算出来 我们传进来的这个ThreadLocal 应该在table数组里的位置 也就是i
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
//然后把i位置上对应的值 赋值进去,有点类似于hashmap的流程
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
//所以这里要明确的就是一个th的值 在table数组里 就对应着一个位置,
} //简单浏览一下Entry的数据结构
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value; Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
} //前面我们简单分析了 threadlocal 第一次被创建时的 存储过程
//然后看我们的set方法 也就是更新threadlocal的过程
//这里的逻辑很简单 当某个线程t 已经有了threadLocals的值以后 第二次再调用set方法 就会走到这里了。第一次调用set方法 可以看上面的createMap流程
//当第二次或者第n次调用set方法 以后 就会根据th的值 在table里遍历 找到这个th对应的值,因为一个线程t 可能有n个不同的th变量。
//这个函数就是根据你传进去的th变量 找到对应的位置 来更新他的值
private void set(ThreadLocal<?> key, Object value) { // We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not. Entry[] tab = table;
int len = tab.length;
//通过我们传进去的theradlocal 取出table数组里的值 table[i]
int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get(); if (k == key) {
e.value = value;
return;
} if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
} tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
} //再来看一下 threadlocal的get方法
public T get() {
Thread t = Thread.currentThread();
//先看看当前线程t的threadLocals 有没有被赋值
ThreadLocalMap map = getMap(t);
//如果不等于null 也就是说当前线程的threadLocals 值已经有了 那我们就直接取对应的value值即可
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//否则我们就给他返回一个初始值 这个初始值 你跟进去看源码就会发现是null了
return setInitialValue();
} //简单分析了 threadlocal 的set和get方法 总结起来就是 他的set和get操作 就是以当前线程为key 取对应的值。可以简单类比想象成是一个哈希表 这个哈希表的key就是线程。
//你要操作th的值 就得把当前的线程t 传到这个表里面 然后取得对应线程t的 对应value 即可。

6.从源码的角度 阐述MessageQueue的原理?

答:

  //我们首先来看一下enqueueMessage的操作 这个操作主要是对消息队列进行一个插入消息的操作
//这个你细细看一下 就是一个很简单的单链表的操作罢了,随意虽然这东西 叫消息队列 但是其实跟队列并没有什么关系
//内部实现为一个链表
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
} synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
} msg.markInUse();
msg.when = when;
//mMessages 这个你可以把他看成是单链表的表头
Message p = mMessages;
boolean needWake;
//当你第一次往消息队列里 插入消息的时候,表头就变成了你第一次传进来的这个消息
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous(); //如果不是第一次传消息
//简单的链表操作不多做分析
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
} // We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
} //next方法就是从消息队列中 取出一个消息 然后删除他
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
} int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
//注意看这个for循环 括号体内是没有break语句的 也就是说这个循环 永远不会退出!如果这个消息队列里没有消息的话
//这个next方法 就阻塞了 因为你仔细看 这个里面没有break语句 只有当取出消息的时候才会return一个message回去
//只有这种情况成立的时候 这个循环才会结束 这个函数才会结束,除此之外 这个函数就永远阻塞在这里
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
} nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
} // Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
} // If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
} if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
} // Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
} if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
} // Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0; // While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}

7.从源码的角度 阐述Looper的原理?

答:

 //这是一个典型的在子线程里创建handler的操作 我们看到在这里创建handler的时候 我们做了2步操作
//第一步是创建looper 第二步是开启消息循环。
new Thread(){
@Override
public void run() {
Looper.prepare();
Handler handler=new Handler();
Looper.loop();
}
}.start(); //我们主要看loop 这个方法 因为只有调用了这个方法 消息循环才真正启动 public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//可以看到 这又是一个死循环
for (;;) {
Message msg = queue.next(); // might block
//唯一跳出循环的方式 就是这个msg 为null 也就是消息队列的next方法返回null
//而next方法返回null的唯一方法 就是调用looper的quit方法 所以这里就能得知
//looper你必须手动帮他退出 否则loop方法就是无限循环下去
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
} // This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
} //这个地方msg 就是发过来的消息,也就是消息队列那个链表里面存储的message ,target就是发送这条消息的handler对象。
//所以这里就能明白最终消息 还是交给handler的dispatchmessage方法来处理的 只不过这个dispatchmessage方法 是在创建handler
//的时候 所使用的looper去执行的 而我们创建looper的时机 正是在线程的run方法里,所以 代码逻辑的最终执行就是在创建handler
//的那个线程里
msg.target.dispatchMessage(msg); if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
} // Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
} msg.recycleUnchecked();
}
}

8.使用looper需要注意什么?

答:不需要的时候 记得终止looper。因为如果你手动处理完毕你需要的业务逻辑以后 如果不调用quit或者quitsafely方法 looper的loop方法就一直执行下去,永远不停止,你这个子线程永远都结束不了。

很容易就内存泄露 或者其他错误,所以我们要牢记 当子线程使用looper的时候 业务处理完毕 记得手动关闭looper。

9.从源码的角度 阐述handler的工作原理?

答:

  //handler有2个发消息的方法一个是post 一个是send 只不过post最终也是走的send
//可以看出来 handler发送消息 其实就是往消息队列里放了一个message罢了
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
} //这是handler处理消息的逻辑 注意这个方法的执行 实在looper所属的线程中。
public void dispatchMessage(Message msg) {
//msg的callback就是runnable对象
if (msg.callback != null) {
//如果你是post方法 实际上handler就是调用你post传进去的那个runnable的run方法而已。
handleCallback(msg);
} else {
//这个实际上就是提供一个 不用派生handler子类时 创建handler对象的方法 虽然我们实际使用中很少使用这种方式
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
} private static void handleCallback(Message message) {
message.callback.run();
} public interface Callback {
public boolean handleMessage(Message msg);
} //看这个构造函数 就能明白为啥创建handler的时候必须得有looper了 所以再一次强调
//在子线程中创建handler的前提条件 是一定得有looper,
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
} mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}

10.android里 主线程的消息循环是怎样实现的?

答:

 //可以看activitythread 的源码
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//创建了主线程的looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//开启了主线程的消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
} //这个就是主线程 的handler 四大组件的启动 停止过程 都在这个里面定义好了 private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public static final int CONFIGURATION_CHANGED = 118;
public static final int CLEAN_UP_CONTEXT = 119;
public static final int GC_WHEN_IDLE = 120;
public static final int BIND_SERVICE = 121;
public static final int UNBIND_SERVICE = 122;
public static final int DUMP_SERVICE = 123;
public static final int LOW_MEMORY = 124;
public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
public static final int RELAUNCH_ACTIVITY = 126;
public static final int PROFILER_CONTROL = 127;
public static final int CREATE_BACKUP_AGENT = 128;
public static final int DESTROY_BACKUP_AGENT = 129;
public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
public static final int SET_CORE_SETTINGS = 138;
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
public static final int TRIM_MEMORY = 140;
public static final int DUMP_PROVIDER = 141;
public static final int UNSTABLE_PROVIDER_DIED = 142;
public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
public static final int INSTALL_PROVIDER = 145;
public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
public static final int CANCEL_VISIBLE_BEHIND = 147;
public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
public static final int ENTER_ANIMATION_COMPLETE = 149;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
case SHOW_WINDOW: return "SHOW_WINDOW";
case HIDE_WINDOW: return "HIDE_WINDOW";
case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
case SEND_RESULT: return "SEND_RESULT";
case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
case BIND_APPLICATION: return "BIND_APPLICATION";
case EXIT_APPLICATION: return "EXIT_APPLICATION";
case NEW_INTENT: return "NEW_INTENT";
case RECEIVER: return "RECEIVER";
case CREATE_SERVICE: return "CREATE_SERVICE";
case SERVICE_ARGS: return "SERVICE_ARGS";
case STOP_SERVICE: return "STOP_SERVICE";
case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
case BIND_SERVICE: return "BIND_SERVICE";
case UNBIND_SERVICE: return "UNBIND_SERVICE";
case DUMP_SERVICE: return "DUMP_SERVICE";
case LOW_MEMORY: return "LOW_MEMORY";
case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
case PROFILER_CONTROL: return "PROFILER_CONTROL";
case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
case SUICIDE: return "SUICIDE";
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
case ENABLE_JIT: return "ENABLE_JIT";
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
case DUMP_HEAP: return "DUMP_HEAP";
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
case SLEEPING: return "SLEEPING";
case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
case TRIM_MEMORY: return "TRIM_MEMORY";
case DUMP_PROVIDER: return "DUMP_PROVIDER";
case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
}
}
return Integer.toString(code);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&1) != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_SHOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, true, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_HIDE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, false, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SHOW_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
handleWindowVisibility((IBinder)msg.obj, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case HIDE_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
handleWindowVisibility((IBinder)msg.obj, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SEND_RESULT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
handleSendResult((ResultData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
msg.arg2, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate();
}
Looper.myLooper().quit();
break;
case NEW_INTENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
handleNewIntent((NewIntentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNBIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
handleUnbindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
handleStopService((IBinder)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
handleConfigurationChanged((Configuration)msg.obj, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
cci.context.performFinalCleanup(cci.who, cci.what);
break;
case GC_WHEN_IDLE:
scheduleGcIdler();
break;
case DUMP_SERVICE:
handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
handleLowMemory();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ACTIVITY_CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
handleActivityConfigurationChanged((ActivityConfigChangeData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PROFILER_CONTROL:
handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
break;
case CREATE_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SUICIDE:
Process.killProcess(Process.myPid());
break;
case REMOVE_PROVIDER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
completeRemoveProvider((ProviderRefCount)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ENABLE_JIT:
ensureJitEnabled();
break;
case DISPATCH_PACKAGE_BROADCAST:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SCHEDULE_CRASH:
throw new RemoteServiceException((String)msg.obj);
case DUMP_HEAP:
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
break;
case DUMP_ACTIVITY:
handleDumpActivity((DumpComponentInfo)msg.obj);
break;
case DUMP_PROVIDER:
handleDumpProvider((DumpComponentInfo)msg.obj);
break;
case SLEEPING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SET_CORE_SETTINGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
handleSetCoreSettings((Bundle) msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
break;
case TRIM_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
handleTrimMemory(msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNSTABLE_PROVIDER_DIED:
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
case REQUEST_ASSIST_CONTEXT_EXTRAS:
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
break;
case TRANSLUCENT_CONVERSION_COMPLETE:
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
break;
case INSTALL_PROVIDER:
handleInstallProvider((ProviderInfo) msg.obj);
break;
case ON_NEW_ACTIVITY_OPTIONS:
Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
onNewActivityOptions(pair.first, pair.second);
break;
case CANCEL_VISIBLE_BEHIND:
handleCancelVisibleBehind((IBinder) msg.obj);
break;
case BACKGROUND_VISIBLE_BEHIND_CHANGED:
handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0);
break;
case ENTER_ANIMATION_COMPLETE:
handleEnterAnimationComplete((IBinder) msg.obj);
break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
private void maybeSnapshot() {
if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
// convert the *private* ActivityThread.PackageInfo to *public* known
// android.content.pm.PackageInfo
String packageName = mBoundApplication.info.mPackageName;
android.content.pm.PackageInfo packageInfo = null;
try {
Context context = getSystemContext();
if(context == null) {
Log.e(TAG, "cannot get a valid context");
return;
}
PackageManager pm = context.getPackageManager();
if(pm == null) {
Log.e(TAG, "cannot get a valid PackageManager");
return;
}
packageInfo = pm.getPackageInfo(
packageName, PackageManager.GET_ACTIVITIES);
} catch (NameNotFoundException e) {
Log.e(TAG, "cannot get package info for " + packageName, e);
}
SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
}
}
}

11.android sdk中都提供了哪些类 扮演着线程的角色?

答:主要是asynctask intentservice 以及handlerthread。其中前者的核心是线程池,后两者的实现核心是线程。intentservice 讲白了就是一个后台线程

只不过这个线程扮演了service的角色 让系统不会轻易的杀死这个线程而已。

12.使用asynctask有哪些注意事项?

答:asynctask的源码分析 我以前写过 这里就不多说了,http://www.cnblogs.com/punkisnotdead/p/4469612.html 可以参考。

主要就是不同版本 asynctask 内部实现不一样。 特别耗时的任务 我们不要放在asynctask 这里做。

  使用要点:

1.asynctask 要在ui线程也就是主线程创建

  2.execute也要在ui线程执行

  3.一个asynctask只能执行一次execute方法。

  4.3.0以后的android版本 asynctask 都是串行执行任务的。(这就是为什么耗时任务不要在这里做的原因 你耗时了 其他资源就用不了了) 3.0以前是并行执行的

  你当然可以用executeOnExecutor来并行执行任务。如果用这个方法 你可以考虑做一些耗时任务。

13.thread和handlerthread的区别在哪?

答:

 //区别主要就在run方法里,thread的run方法就是执行一个耗时任务
//而hh 在内部创建了消息队列。 @Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
//这里开启消息循环 会在消息队列的next方法那边block住,所以你不用的时候 一定记得quit!
Looper.loop();
mTid = -1;
}

14.intentservice的原理?

答:

 //intentservice 在onCreate方法里启动了一个handlerthread
//注意service的onCreate方法 只在第一次启动时候才被调用
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock. super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start(); mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
} //而service的onStartCommand 是每次启动都被调用的
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
} //所以你看startservice 发送的intent 被传送到了这里
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
} //intent发送到这里被处理
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
} @Override
public void handleMessage(Message msg) {
//处理完我们的intent 就结束了 所以这个intentservice 也是顺序执行任务的
onHandleIntent((Intent)msg.obj);
//stopself方法是立即停止 而我们这是是用的stopself(int startId) 这个方法会等待所有消息处理完毕以后才停止
stopSelf(msg.arg1);
}
} //这个方法教给子类去实现的。
@WorkerThread
protected abstract void onHandleIntent(Intent intent);

15.在android中使用线程池 有什么需要注意的地方?

答:其实android中的线程池 跟java中的一模一样。就是通过Executor接口来操作的。

 package com.example;

 /**
* Created by Administrator on 2016/2/15.
*/ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; /**
* 理解好线程池 主要就是理解好核心线程这个概念 核心线程 的意思 就是永远不消亡,不存在超时机制,核心线程会一直存在与线程池之中 闲置状态也会一直存在。
* 非核心线程 超时以后 就自动被线程池回收了
* 所以根据这一点 我们就可以根据我们的业务模型 选择合适的线程池。
*/
public class ThreadExcutorsExample { public static void main(String[] args)
{
//这种线程池只有核心线程,这些线程永远不会被回收的。所以这种线程池适合 需要快速响应外界请求的 场景。
ExecutorService fixedThreadPool= Executors.newFixedThreadPool(4); //这种线程池 没有核心线程,全都是非核心线程,超时时间为60s 也就是说超过60s 没有任务进来处理 就自动销毁.
//最大线程数就是Intger。Maxvalue 理论上就是可以开启无线个线程。
//当没有任务进来的时候 这个线程池 就没有线程了。所以适合执行 大量耗时较少的场景
ExecutorService cacheThreadPool=Executors.newCachedThreadPool(); //核心线程数量固定 非核心线程没有限制, 定时任务什么的 可以用这个 比较合适
ExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(4); //就只有一个核心线程,非核心线程也没有。所以这种线程池就是顺序处理任务的
ExecutorService singleThreadPool=Executors.newSingleThreadScheduledExecutor(); // 他们内部都是通过ThreadPoolExecutor这个构造方法 来构造对应的线程池的。asynctask 不同版本的源码 你都可以看看 是怎么构造的。
// 其实都是这个构造函数 传递了不同的参数而已。
// public ThreadPoolExecutor(int corePoolSize,
// int maximumPoolSize,
// long keepAliveTime,
// TimeUnit unit,
// BlockingQueue<Runnable> workQueue) {
// this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
// Executors.defaultThreadFactory(), defaultHandler);
}
}
}

Android 线程与消息 机制 15问15答的更多相关文章

  1. 浅析Android中的消息机制(转)

    原博客地址:http://blog.csdn.net/liuhe688/article/details/6407225 在分析Android消息机制之前,我们先来看一段代码: public class ...

  2. 浅析Android中的消息机制(转)

    在分析Android消息机制之前,我们先来看一段代码: public class MainActivity extends Activity implements View.OnClickListen ...

  3. 浅析Android中的消息机制-解决:Only the original thread that created a view hierarchy can touch its views.

    在分析Android消息机制之前,我们先来看一段代码: public class MainActivity extends Activity implements View.OnClickListen ...

  4. 浅析Android中的消息机制

    在分析Android消息机制之前,我们先来看一段代码: public class MainActivity extends Activity implements View.OnClickListen ...

  5. Android中的消息机制

    在分析Android消息机制之前.我们先来看一段代码: public class MainActivity extends Activity implements View.OnClickListen ...

  6. 重温Android中的消息机制

    引入: 提到Android中的消息机制,大家应该都不陌生,我们在开发中不可避免的要和它打交道.从我们开发的角度来看,Handler是Android消息机制的上层接口.我们在平时的开发中只需要和Hand ...

  7. 谈谈对Android中的消息机制的理解

    Android中的消息机制主要由Handler.MessageQueue.Looper三个类组成,他们的主要作用是 Handler负责发送.处理Message MessageQueue负责维护Mess ...

  8. Android线程间异步通信机制源码分析

    本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...

  9. Android View事件机制 21问21答

    原文: http://www.cnblogs.com/punkisnotdead/p/5179115.html#3358859 1.View的坐标参数 主要有哪些?分别有什么注意的要点? 答:Left ...

随机推荐

  1. Session、Cookie及cache的区别

    Session 是单用户的会话状态.当用户访问网站时,产生一个 sessionid.并存在于 cookies中.每次向服务器请求时,发送这个 cookies,再从服务器中检索是否有这个 session ...

  2. lintcode:将二叉树拆成链表

    题目 将一棵二叉树按照前序遍历拆解成为一个假链表.所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针. 注意事项 不要忘记将左儿子标记为 null,否则你可能会得到空间溢出 ...

  3. IIS7 ASP.NET 未被授权访问所请求的资源

    IIS7 ASP.NET 未被授权访问所请求的资源 ASP.NET 未被授权访问所请求的资源.请考虑授予 ASP.NET 请求标识访问此资源的权限. ASP.NET 有一个在应用程序没有模拟时使用的基 ...

  4. Fatal error: cannot allocate memory for the buffer pool

    mysql有时候会被系统kill掉,原因是内存不够了,一般都是Ubuntu出现的,因为Ubuntu吃内存,你们又给的不多.. 咋解决呢? 重启服务器是可以的,起码暂时可以了, 可以考虑加内存,或者增加 ...

  5. VS2010/MFC编程入门之五(MFC消息映射机制概述)

    VS2010/MFC编程入门之五(MFC消息映射机制概述)-软件开发-鸡啄米 http://www.jizhuomi.com/software/147.html 上一讲鸡啄米为大家简单分析了MFC应用 ...

  6. 【web性能】让css更简洁、高效

    用了这么多年的CSS,现在才明白CSS的真正匹配原理,不知道你是否也跟我一样?   看1个简单的CSS: DIV#divBox p span.red{color:red;},按习惯我们对这个CSS 的 ...

  7. USACO Section 3.4: Raucous Rockers

    简单的dfs题目 /* ID: yingzho1 LANG: C++ TASK: rockers */ #include <iostream> #include <fstream&g ...

  8. 安卓自动化测试之MonkeyRunner环境的搭建

    最近在抽时间学习一些安卓自动化的知识,把学到东西都就记录下来,避免以后记性不好忘记,也方便对自己积累知识的查阅 MonkeyRunner是基于坐标点来操作控件的,你可以通过写python脚本来调用mo ...

  9. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  10. Linux内核基础--事件通知链(notifier chain)

    转载: http://blog.csdn.net/wuhzossibility/article/details/8079025 http://blog.chinaunix.net/uid-277176 ...