美文网首页
Handler原理

Handler原理

作者: 愿你我皆是黑马 | 来源:发表于2021-12-21 13:25 被阅读0次

最近在画各种图,所以这里贴贴图来说明一下


Handler通信的基本原理

  • 为什么Handler这样用Loop搞一下,就能主子线程通信了? 上面的图按颜色区分是在哪个线程执行的逻辑

创建Looper


主线程赋值mHandler变量具体实例mHander=new Handler()的过程:

  1. 构造Handler时候传的构造参数async为false:同步消息
  2. 构造Handler时候传的构造参数async为true :异步消息
  3. Message调用setAsynchronous=true(当Handlerasync为false时有效):异步消息
  4. static Handler createAsync(@NonNull Looper looper):异步消息(28)
  • 上述两种消息在有 同步屏障(在下面会提到) 的时候有区别

sendMessage发送消息流程

一般不在这里唤醒Looper,除非:图中(贴代码的部分) 一开始的唤醒判断为true,并且传入消息参数的是最早的异步消息


loop.loop流程

  • next()获取消息

先发一下看看用图片的效果,后面的继续补充


唤醒和挂起


同步屏障:在取消息的时候,会暂时忽略同步消息,只处理异步消息和等待异步消息插入

  • 添加同步屏障流程
  • 屏障同样是根据时间来插入到队列中适当位置,且只会挡住后面的同步消息

  • 插入屏障不会唤醒消息队列

  • 代码添加同步屏障

    //获取当前线程Looper对象的消息队列
    MessageQueue queue=handler.getLooper().getQueue();
    //通过反射调用
    Method method=MessageQueue.class.getDeclaredMethod("postSyncBarrier");
    method.setAccessible(true);
    token= (int) method.invoke(queue);
    
  • 移除同步屏障流程

  • 代码移除同步屏障
    //移除同步屏障
    //获取当前线程Looper对象的消息队列
    MessageQueue queue=handler.getLooper().getQueue();
    Method method=MessageQueue.class.getDeclaredMethod("removeSyncBarrier",int.cla  ss);
    method.setAccessible(true);
    method.invoke(queue,token);
    

移除消息


为什么建议使用obtain获取Message

  • recycleUnchecked源码如下:
     @UnsupportedAppUsage
     void recycleUnchecked() {
         // Mark the message as in use while it remains in the recycled object pool.
         // Clear out all other details.
         flags = FLAG_IN_USE;
         what = 0;
         arg1 = 0;
         arg2 = 0;
         obj = null;
         replyTo = null;
         sendingUid = UID_NONE;
         workSourceUid = UID_NONE;
         when = 0;
         target = null;
         callback = null;
         data = null;
    
         synchronized (sPoolSync) {
             if (sPoolSize < MAX_POOL_SIZE) {
                 next = sPool;
                 sPool = this;
                 sPoolSize++;
             }
         }
     }
    

其他API (public)

  • MessageQueue类
    1. 是否处理空闲状态: boolean isIdle()
    2. 添加空闲时处理的消息:void addIdleHandler(IdleHandler handler)
    3. 移除空闲时处理的消息:void removeIdleHandler(IdleHandler handler)
    4. 是否没有被阻塞,当前处理轮询事件中:boolean isPolling()
    5. 无参的的同步屏障:int postSyncBarrier()
    6. 移除同步屏障:removeSyncBarrier(int token)
  • Handler类
    1. 直接跳到分发消息这一步:dispatchMessage(Message msg)
      与上面的类似(上面是在当前handler处理),还有个 当前handler往主handler塞有延迟时间的处理消息:runWithScissors()
    2. (静态方法)不通过构造方法,而是用方法构造异步消息:static Handler createAsync(Looper loop)、static Handler createAsync(Looper loop,Callback callback)
    3. (静态方法)获取系统主Handler没有再getMainLooper创建一个:static Handler getMain()
    4. (静态方法)如果参数Handler是空的,则使用主Handler:static Handler mainIfNull(Handler handler)
    5. 崩溃时控制台打印的字符串定义:String getTraceName(Message message)
    6. 获取handler绑定的Looper:Looper getLooper()

简要提提延伸

  1. Message.obtain()
  2. Handler泄露
  3. 各种内置子线程的Handler实现
  4. IdleHandler
  5. 判断主线程
  6. 优先级链表
  7. 线程本地

相关文章

网友评论

      本文标题:Handler原理

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