zoukankan      html  css  js  c++  java
  • 一个例子了解 HandlerThread,Looper,ThreadLocal,Handler,MessageQueue,Message的关系

    我们经常会用到 HandlerThread 在线程中执行Runnable方法,调用代码如下,

    private HandlerThread mHandlerThread = new HandlerThread("MainActivity");
    mHandlerThread.start();
    mWorkHandler = new Handler(mHandlerThread.getLooper());
    mWorkHandler.post(new Runnable() {
      @Override
      public void run() {

      }
    });
    相关机制是怎么触发的呢?
    这里面涉及到HandlerThread,Looper,ThreadLocal,Handler,MessageQueue,Message 等概念,流程如下:

    1.mHandlerThread.start();
    本身继承Thread,该方法启动线程,
    HandlerThread run方法
    HandlerThread.run相关代码如下:
    public void run() {
      mTid = Process.myTid();
      Looper.prepare();
      synchronized (this) {
      mLooper = Looper.myLooper();
      notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
    }

    1.1 执行 Looper.prepare()
      Looper.prepare() 创建Looper实例放在 sThreadLocal 对象里面, 调用如下:
      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));
      }
    1.2 Looper.myLooper()方法从 sThreadLocal 中获取Looper实例(这个实例是线程独立的,即获取的是对应线程创建的Looper实例)
      给 HandlerThread 的全局变量 mLooper

      public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
      }

    1.3 执行Looper.loop()创建消息循环,
      核心逻辑是从 当前线程的Looper中取出 MessageQueue,循环遍历 MessageQueue 中的消息
      Looper.loop()代码
      public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        ...
      }

    2.new Handler(mHandlerThread.getLooper())
      2.1 mHandlerThread.getLooper() 获取HandlerThread 中创建的 Looper对象
      2.2 把获取的Looper初始化到Hander中
    3. mWorkHandler.post(new Runnable()..)
      3.1通过 getPostMessage 方法将Runnable封装到 Message 对象中
      3.2 最终会调用sendMessageAtTime方法
      该方法中MessageQueue对象 mQueue 就是从2.1 Hander中Lopper中获取的,而且这个MessageQueue 在1.3 消息循环中不停的被遍历,
      你只要向 MessageQueue 中添加Runnable封装 Message,就会在指定的时间执行 Runnable方法。
     

    Handler.java 相关调用代码如下:
      public final boolean post(Runnable r)
      {
        return sendMessageDelayed(getPostMessage(r), 0);
      }

      private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
       return m;
     }

      public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
          RuntimeException e = new RuntimeException(
          this + " sendMessageAtTime() called with no mQueue");
          Log.w("Looper", e.getMessage(), e);
          return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
      }

  • 相关阅读:
    一个小程序的经验总结
    my favorite computer publishers
    关于在天涯看小说
    书店
    Server 2003&Windows 7&Server 2008 R2&Visual Studio&MSDN: my personal best practice
    Google搜索:基本语法
    【我喜欢的一篇文章】Fire And Motion
    Windbg学习笔记(1)
    如何清除Help Viewer 2.0之Filter Contents中的列表内容
    5年了,难道我真的不适合做一个程序员吗,请告诉我我该怎么做?
  • 原文地址:https://www.cnblogs.com/adamli/p/13408190.html
Copyright © 2011-2022 走看看