Android开发Android技术知识Android开发经验谈

Handler、Looper源码学习

2018-11-20  本文已影响5人  kevinsong0810

Android中,使用Handler,Looper的场景主要是跨线程通信,先看一个简单的例子:

public class MainActivity extends Activity {
    public final static int MESSAGE_TYPE_1 = 1;

    private WorkHandler mHandler;
    private static class WorkHandler extends Handler {
        public WorkHandler(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_TYPE_1:
                    LogUtils.d("this is message 1");
                    // do something...
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        HandlerThread thread = new HandlerThread("work_thread"); // 创建一个线程对象
        thread.start(); // 启动子线程,这时会利用HandlerThread#run方法,创建一个Looper对象,绑定子线程,线程的执行并进入loop循环模式
        mHandler = new WorkHandler(thread.getLooper()); // 创建一个Handler对象,并传入Looper

        Message msg = new Message();
        msg.what = MESSAGE_TYPE_1;
        mHandler.sendMessage(msg); // 通过主线程发送1个消息,消息被压入messageQueue(所属于Looper对象)
    }
}

这里涉及到4个重要的类:Handler,Looper,MessageQueue(Handler和Looper的成员变量),HandlerThread。

1. Handler
public class Handler {
      final Looper mLooper; 
      final MessageQueue mQueue;

      public Handler(Looper looper, Callback callback, boolean async) {
           mLooper = looper;
           mQueue = looper.mQueue;
           // ...
     }
}

Handler类有2个成员变量,mLooper和mQueue,从构造函数可看出,mQueue用的也是Looper的成员变量。所以本质上Handler含有1个Looper对象。
Handler有2个重要的方法,我们经常用到,sendMessage和handleMessage。

2. Looper

Looper类有2个重要的成员变量,mQueue和mThread,另外还有1个所属于进程的sThreadLocal集合,ThreadLocal<Looper>本质是一个Map数据结构,key是线程对象,value是Looper对象。它的作用是保存进程中所有<Thread,Looper>的信息,保证Looper对象和线程1:1对应。

public final class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    final MessageQueue mQueue;
    final Thread mThread;
    // ...
}

Looper有3个重要的静态方法:prepare,prepareMainLooper,loop。

private static void prepare(boolean quitAllowed) {
     if (sThreadLocal.get() != null) {
         throw new RuntimeException("Only one Looper may be created per thLooper.prepare,Looper.loop等read");
     }
     sThreadLocal.set(new Looper(quitAllowed));
}
public static void prepareMainLooper() {
      prepare(false); // false代表参数quitAllowed的值,表示不允许退出
      synchronized (Looper.class) {
          if (sMainLooper != null) {
              throw new IllegalStateException("The main Looper has already been prepared.");
          }
          sMainLooper = myLooper();
      }
}
    public static void loop() {
        // ...
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // ...
            msg.target.dispatchMessage(msg);
            // ...
        }
    }
3. MessageQueue

MessageQueue的实现较为复杂,主要是利用JNI,调用native相关方法,例如MessageQueue初始化时,调用nativeInit();
代码路径:frameworks/base/core/jni/android_os_MessageQueue.cpp
这里暂时先不深入研究,后面再补充。

4. HandlerThread

HandlerThread的实现很简单,继承于Thread类。作用是封装一个默认带Looper的Thread类,省去开发者自己调用Looper.prepare,Looper.loop等方法,使Handler的使用更方便。如本文开始的例子。
HandlerThread的核心方法是重写的run方法,其中会调用Looper.prepare,Looper.loop等。

总结:

上一篇 下一篇

猜你喜欢

热点阅读