Looper、Handler、MessageQueue在ActivityThread中的源码剖析(原创)

最近阅读深入理解android内核设计思想这本书,第一次接触android内核源码,看着是既枯燥又枯燥,当然看源码要从ui主线程看起,这里剖析下ActivityThread中looper、handler、message在里面的关系。

这里在source insight进入ActivityThread的void main方法中:

public static void main(String[] args) {
         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());

         Security.addProvider(new AndroidKeyStoreProvider());

         // 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.prepareMainLooper();

         ActivityThread thread = new ActivityThread();
         thread.attach(false);

         if (sMainThreadHandler == null) {
             sMainThreadHandler = thread.getHandler();
         }

         AsyncTask.init();

         if (false) {
             Looper.myLooper().setMessageLogging(new
                     LogPrinter(Log.DEBUG, "ActivityThread"));
         }

         Looper.loop();

         throw new RuntimeException("Main thread loop unexpectedly exited");
     }
}

可以看到这里和普通线程循环读取消息序列不同:
1、普通线程使用prepare()就行了,主线程使用的是premMainlooper();
2、普通线程会在中间创建一个帮的looper的handler对象,而主线程会从当前线程获取到主线程的handler(gethandler)。
针对1,打开premainlooper源码:

public static void prepareMainLooper() {
         prepare(false);
         synchronized (Looper.class) {
             if (sMainLooper != null) {
                 throw new IllegalStateException("The main Looper has already been prepared.");
             }
             sMainLooper = myLooper();
         }
     }
这里可以看出premainlooper和调用了prepare方法,参数false表示不允许退出,经过prepare后mylooper会得到一个与本地线程的looper对象,然后赋值给sMainLooper对象,所以主线程的looper和其他码农手写的looper没有本质区别的。
打开prepare()源码
private static void prepare(boolean quitAllowed) {
         if (sThreadLocal.get() != null) {
             throw new RuntimeException("Only one Looper may be created per thread");
         }
         sThreadLocal.set(new Looper(quitAllowed));
     }
<\code>

<code lang="java">
public static Looper myLooper() {
         return sThreadLocal.get();
     }
总结:可以看到prepare()方法为当前线程sThreadLocal生成了一个looper,即myLooper,然后preparemainlooper中再让sMainLooper指向myLooper即指向当前线程的Looper对象,到这里,ui主线程中looper的创建工作完成。
———————————–
第二步当然是绑定与Thread绑定的handler了
这里调用getHander方法,获得handler,

mH是一个H对象

1
private class H extends Handler

ok 明白H是个Handler对象就行了,sMainThreadHandler会一直从当前线程通过getHandler方法获得handler对象,然后进入下一步,最关键的异步.loop()方法。
——————————————-
进入Looper.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
             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.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();
         }
     }

ok
这里会先获取到looper对象的消息队列messagequeue,然后进入死循环for(;;),不断的.next获取到最前的msg,然后进入关键一步msg.target.dispatchMessage(msg);打开这里的target就是执行消息队列任务的handler,而dispatchMessage进入源码看下是什么:

public void dispatchMessage(Message msg) {
         if (msg.callback != null) {
             handleCallback(msg);
         } else {
             if (mCallback != null) {
                 if (mCallback.handleMessage(msg)) {
                     return;
                 }
             }
             handleMessage(msg);
         }
     }

这里会执行一个handlemessage方法,这也是为什么在我们通过创建一个handler时为什么要重写handlemessage的原因,而且我们还要手动的通过handler的sendmessage方法发送一个消息。
———————————————
到此ActivityThread中消息循环机制完成,总结下:
1、prepareMainLooper 进行消息队列的创建,生成looper对象,且让sMainLooper指向它
2、通过gethandler获取当前线程handler,指向一个H对象
3、进入Looper死循环不断地获取消息并且让handlemessge去处理。

这和普通线程在本质上是完全一样的。
———-
纯手打,转载请注明出处



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值