Handler

作者: 内卷程序员 | 来源:发表于2022-08-28 02:46 被阅读0次

    android开发中,在子线程中进行一些操作完成后会通过handler发送一些数据给主线程。 生产者-消费者模型:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加数据, 消费者从存储空间中取走数据。跨线程的核心就是共享内存。

    handler整体流程

    image.png

    子线程 - 将消息插入队列的节点

    handler -> sendMessage -> enqueueMessage -> messasgeQueue.enqueueMessage

    主线程 - 将消息从队列里面取出分发

    looper.loop() -> messasgeQueue.next() -> handler.dispatchMessage() -> handler.handleMessage()

    image.png

    一、Handler的创建是与Looper创建的线程是相同的。
    二、Looper中内部维护了一个MessageQueue(也就是消息队列)。且该队列是通过链表的形式实现优先级队列。
    三、Hanlder最终通过sendMessage方法将消息发送到Looper中对应的MessageQueue中。
    四、Looper通过消息循环获取消息后,会调用对应的消息中的target(target对应的是发消息的Handler)的dispatchMessage()方法来处理消息。

    Looper原理

    class ActivityThread {
    
     public static void main(String[] args) {
            ...
           //准备主线程looper
            Looper.prepareMainLooper();
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
            ...
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           //启动 Looper 开启消息循环
            Looper.loop();
           ...
        }
    }
    
    public final class Looper {
    
      final MessageQueue mQueue;
      final Thread mThread;
    
      //Looper内部会创建MessageQueue对象
      private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
    
       //创建主线程Looper对象 判断looper是否被创建 保存主线程的looper对象
       public static void prepareMainLooper() {
          //false表示消息队列不能被清除
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                //当前Looper对象已经与主线程关联了
                sMainLooper = myLooper();
            }
        }
      //Looper与当前主线程绑定
      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));//创建Looper对象,放入主线程局部变量中
        }
      //获取当前主线程的Looper对象
      public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
       }
     
    //当前Looper对象与主线程关联后,接着会调用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;
            //...省略部分代码
            for (;;) {//一直循环去获取消息队列中的消息
                Message msg = queue.next(); //该方法可能堵塞,
                if (msg == null) {
                    //如果没有消息,表示当前消息队列已经退出
                    return;
                }
               //...省略部分代码
                try {
                 //获取消息后,执行发送消息的handler的dispatchMessage方法。
                    msg.target.dispatchMessage(msg);
                    end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
               //...省略部分代码
                }
                msg.recycleUnchecked();
            }
      //quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息。无论是调用了quit方法还是quitSafely方法只会,Looper就不再接收新的消息
        public void quit() {
            mQueue.quit(false);
        }
     
        public void quitSafely() {
            mQueue.quit(true);
        }
        }
    

    MessageQueue 原理 - 入队出队

    class MessageQueue{
    
        void quit(boolean safe) {
            synchronized (this) {
                if (mQuitting) {
                    return;
                }
                mQuitting = true;
    
                if (safe) {
                  // 清空消息之前会派发所有的非延迟消息
                    removeAllFutureMessagesLocked();
                } else {
                  //清空全部消息
                    removeAllMessagesLocked();
                }
    
                // We can assume mPtr != 0 because mQuitting was previously false.
                nativeWake(mPtr);
            }
        }
    
    
    //消息队列的加入过程
    boolean enqueueMessage(Message msg, long when) {
              //...省略部分代码
            synchronized (this) {
              //...省略部分代码
                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 {
                  //...省略部分代码
                    //循环遍历消息队列,把当前进入的消息放入合适的位置(比较等待时间)
                    for (;;) {
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    }
                    //将消息插入合适的位置
                    msg.next = p;
                    prev.next = msg;
                }
              //...省略部分代码
            }
            return true;
         }
    
       //MessageQueue中去获取消息,直到获取消息后才会退出
      Message next() {
        //...省略部分代码
         for (;;) {
             nativePollOnce(ptr, nextPollTimeoutMillis);//睡眠
             synchronized (this) {
             //...省略部分代码
             final long now = SystemClock.uptimeMillis();
              Message prevMsg = null;
              Message msg = mMessages;
              if (msg != null && msg.target == null) {
                 // 同步屏障,类似于救护车需要优先通过执行,比如更新UI,先发送同步屏障,然后再发送同步消息,循环所有消息,发现有同步消息并且是更新UI 马上出来 Async 表示刷新UI消息
                 do {
                       prevMsg = msg;
                       msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                  }
             if (msg != null) {
              //对比消息执行时间是不是大于当前时间
               if (now < msg.when) {
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); //计算下次执行时间
                        } else {
                            //遍历消息列表,取出消息
                            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; //没有消息就一直睡眠
                    }
                    //
                    if (mQuitting) {
                        dispose();
                        return null;
                    }
          }
        }
    }
    

    Handler的原理

    public class Handler {
    
    //不带Looper的构造函数,是通过Looper.myLooper()来获取当前主线程的Looper对象 
      public Handler() {this(null, false);}
      public Handler(boolean async) {this(null, async);}
      public Handler(Callback callback) {this(callback, false);}
      public Handler(boolean async) {this(null, async);}
      public Handler(Callback callback, boolean async) {
            //Looper.myLooper()内部会调用sThreadLocal.get(),获取线程中保存的looper局部变量
            mLooper = Looper.myLooper();
            if (mLooper == null) {
                throw new RuntimeException(
                    "Can't create handler inside thread that has not called Looper.prepare()");
            }
            //获取当前Looper中的MessageQueue
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
     //带Looper参数的构造函数是线程已经通过Looper.prepare()与Looper.loop()构建了自己的循环消息队列, 只有调用了该方法后,才会将当前Looper对象放入线程的局部变量中**可以构建自己的消息处理循环,比如HandlerThread 
      public Handler(Looper looper) { this(looper, null, false); }
      public Handler(Looper looper, Callback callback) { this(looper, callback, false);}
      public Handler(Looper looper, Callback callback, boolean async) {
            mLooper = looper;
            //获取当前Looper中的MessageQueue
            mQueue = looper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
      }  
     
    
    
    //handler发送到MessaageQueue(消息队列)中去
    //发送及时消息
    public final boolean sendMessage(Message msg)
    public final boolean sendEmptyMessage(int what)
    public final boolean post(Runnable r)
    //发送延时消息
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    public final boolean postDelayed(Runnable r, long delayMillis)
    //发送定时消息
    public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
    public final boolean postAtTime(Runnable r, long uptimeMillis)
    
    //所有发送的消息最后都会调用到enqueueMessage
    private boolean enqueueMessage(MessageQueue queue,Message msg,long uptimeMillis) {
        //handler 赋值给msg的变量中,最后分发的时候取出该handler进行分发
          msg.target = this;
          msg.workSourceUid = ThreadLocalWorkSource.getUid();
          return queue.enqueueMessage(msg, uptimeMillis);
    }
    
    //Looper会调用loop()方法循环的取消息。当取出消息后会调用message.target.dispatchMessage(msg)方法
    public void dispatchMessage(Message msg) {
         if (msg.callback != null) {  
            //第一步,判断msg.callback  handler.post()系列方法的时候
             handleCallback(msg);
         } else {
             if (mCallback != null) {
            //第二步、判断Handler的callBack
                 if (mCallback.handleMessage(msg)) {
                     return;
                 }
             }
             //第三步,执行Handler的handleMessage方法
             handleMessage(msg);
         } 
    }
    
    handler.post()系列方法的时候会调用该方法
    private static Message getPostMessage(Runnable r) {
          Message m = Message.obtain();
          m.callback = r;
          return m;
     }
    private static void handleCallback(Message message) {
          message.callback.run();
       }
    

    handler 问题 https://www.jianshu.com/p/f5722e1e8e6c

    相关文章

      网友评论

          本文标题:Handler

          本文链接:https://www.haomeiwen.com/subject/gseqnrtx.html