在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作。
为了达到这个目的Android设计了handler Looper这个系统框架。
首先讲解在主线程中使用Handler时源码跟踪过程。
正常在activity的oncreate函数中定义个handler,这种情况下就是默认的主线程的handler,并去复写该类的handleMessage()函数。
private final Handler mMessageHandler = new Handler(){ @Override public void handleMessage(Message msg){ ....; } }
在这里new 了一个Handler类,跟入系统代码
106 /** 107 * Default constructor associates this handler with the {@link Looper} for the 108 * current thread. 109 * 110 * If this thread does not have a looper, this handler won‘t be able to receive messages 111 * so an exception is thrown. 112 */ 113 public Handler() { 114 this(null, false); 115 }
188 public Handler(Callback callback, boolean async) { 189 if (FIND_POTENTIAL_LEAKS) { 190 final Class<? extends Handler> klass = getClass(); 191 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 192 (klass.getModifiers() & Modifier.STATIC) == 0) { 193 Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 194 klass.getCanonicalName()); 195 } 196 } 197 198 mLooper = Looper.myLooper(); 199 if (mLooper == null) { 200 throw new RuntimeException( 201 "Can‘t create handler inside thread that has not called Looper.prepare()"); 202 } 203 mQueue = mLooper.mQueue; 204 mCallback = callback; 205 mAsynchronous = async; 206 }
最后需要对mQueue;mCallback;mAsynchronous这三个变量赋值。
这里注意 mLooper = Looper.myLooper(); 对mLooper的初始化。这里进入了Looper类
191 public static @Nullable Looper myLooper() { 192 return sThreadLocal.get(); 193 }
68 // sThreadLocal.get() will return null unless you‘ve called prepare(). 69 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
92 private static void prepare(boolean quitAllowed) { 93 if (sThreadLocal.get() != null) { 94 throw new RuntimeException("Only one Looper may be created per thread"); 95 } 96 sThreadLocal.set(new Looper(quitAllowed)); 97 } 98
最后new Looper(quitAllowed) 在这里在当前thread中新建了一个Looper对象(所以从这里可以看出来Looper是属于当前thread的)。
正常在我们自己new的线程中都需要调用Looper.prepare();语句来为当前线程new一个looper对象。但是对于UI线程中创建的looper是不需要的,因为在初始化UI线程时就已经写好了。
正常UI线程初始化时调用prepareMainLooper这个函数。
99 /** 100 * Initialize the current thread as a looper, marking it as an 101 * application‘s main looper. The main looper for your application 102 * is created by the Android environment, so you should never need 103 * to call this function yourself. See also: {@link #prepare()} 104 */ 105 public static void prepareMainLooper() { 106 prepare(false); 107 synchronized (Looper.class) { 108 if (sMainLooper != null) { 109 throw new IllegalStateException("The main Looper has already been prepared."); 110 } 111 sMainLooper = myLooper(); 112 } 113 }
对于一般的子线程需要继续调用Looper.loop来启动loop循环进行消息发送。
而同样对于UI线程的looper同样是在初始化过程中已经调用好了。
128 public static void loop() { 129 final Looper me = myLooper(); 130 if (me == null) { 131 throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread."); 132 } 133 final MessageQueue queue = me.mQueue; .............. 142 for (;;) { 143 Message msg = queue.next(); // might block 144 if (msg == null) { 145 // No message indicates that the message queue is quitting. 146 return; 147 } 。。。。。。。。。。 158 msg.target.dispatchMessage(msg);
在这个loop()函数中就能真正看到消息循环机制。在一个死循环中for(;;)不断从queue消息队列中获取messager,如果没有将阻止在该端口等待下一个messager。
在获取一个消息后则放入message中的targe中进行消息分发。
这里的target其实就是最开始在封装一个message进行发送时传入的handler,所以从这里也可以看出,最后消息还是通过handler传入到它所在的线程中调用handleMessage()进行处理。
message.java 的成员变量:
public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; public Messenger replyTo; public int sendingUid = -1; /*package*/ static final int FLAG_IN_USE = 1 << 0; /** If set message is asynchronous */ /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1; /** Flags to clear in the copyFrom method */ /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; /*package*/ int flags; /*package*/ long when; /*package*/ Bundle data; /*package*/ Handler target /*package*/ Runnable callback; // sometimes we store linked lists of these things /*package*/ Message next;
。。。。