android机制系列之3.1 Handler实现原理补充

系列之三 线程间通信-Handler 补充
系列目录 https://blog.csdn.net/jzlhll123/article/category/7671581

今天补充一个话题:
1. 是否可以对同一个Thread,Looper,建立2个Handler?
2. 如果可以,这2个Handler的运行顺序是否排队?是否可以相互接收到对方msg?

答案显然是:
1. 可以,使用Handler(Looper)创建多个;
2. 他们的消息是排队在线程内处理的,并且不能相互接收。

我们来分析下原理。
Thread
Handler


我们再次复习下Looper的源码。Looper的方法基本都是static的,这是因为Looper是跟Thread绑定的,一个thread只有一个Looper。原理:

public static final void prepare() {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}

第一步Looper.prepare()流程
sThreadLocal.set(new Looper(boolean)), 由于是静态的,一个进程多次prepare()会报错。这将Looper跟Thread绑定到一块,Looper成为了Thread的一个成员变量。

private Looper() { //构造函数
  mQueue = new MessageQueue();
  mRun = true;
  mThread = Thread.currentThread();
}

new Looper()的时候,会创建唯一的一个MessageQueue,因此,同一个Thread也只有一个Queue;
第二步loop()流程

public static final void loop() {
   Looper me = myLooper(); //sThreadLocal.get()拿出来,线程唯一的一个变量
   MessageQueue queue = me.mQueue;
    //...
   while (true) {
       Message msg = queue.next(); //如果没事干就阻塞在这里
       if (msg != null) {
           if (msg.target == null) {
               return;
           }
           //...
           msg.target.dispatchMessage(msg);
            //...
           msg.recycle();
       }
   }
}

queue.next()里面 for (;;) { 开启了一个死循环,如果没有消息则会阻塞。


2. sendMessage
  Handler new的时候,将looper传进去,成为成员变量mLooper, 同时从mLooper拿出queue,也成为成员变量mQueue. 因此,结合上面我们知道多个Handler其实共享同一个Looper,同一个messageQueue。
  不论是sendMessage,sendMessageDelay,post等,最终都是sendMessageAtTime->enqueueMessage(queue, msg, uptimeMillis) 在这里给msg.target=this,打上了跟每个具体Handler实例的印记(标注3)-> queue.enqueueMessage.
  然后在MessageQueue代码中,给Message进一步根据是否有添加next节点等将所有的message进行一次队列串联。最后nativeWake(标注2)。


3. dispatchMessage&handleMessage
  我们来看标注1和标注2. 标注1处queue.next()内部会nativePollOnce,达到一个等待的状态;标注2 msg过来以后唤醒了next()可以继续下去。(这就解释了Handler的模型)。
  然后,next()返回,msg.target.dispatchMessage(msg);, 也就是标注3,这里将msg分发给具体的Handler。
  最后独特的Handler自己的handleMessage(msg)收到了自己的msg。


所以,使用的时候,我们可以创建多个Handler,但是可以通过控制Thread的个数,来让自己的一些业务逻辑排队。

猜你喜欢

转载自blog.csdn.net/jzlhll123/article/details/80597948