欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

源码解析 Handler机制

程序员文章站 2022-07-14 16:46:22
...

系统为什么不允许在子线程里访问UI?那是因为Android的UI控件线程不安全,如果多线程并发访问的话会导致UI控件处于不可预期的状态。

ThreadLocal 工作原理

ThreadLocal是一个线程内部的储存类,通过它可以在指定的线程中存储数据,数据储存以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。

Handler机制 四种主体类

  • Lopper:消息轮训器
  • MessageQueue:消息队列
  • Handler:处理消息
  • Message:消息对象

开启应用时

  • 1) ActivityThread.java
    当应用启动时,会调用ActivityThread的main方法,在main方法里调用prepareMainLooper()方法和loop()方法
// ActivityThread.java
public static void main(String[] args) {
    Looper.prepareMainLooper();
    ........ 
    Looper.loop();
}
  • 2)Looper.java
    #1 在prepare()方法里回去获取当前的Looper,如果没有的话(启动应用时是没有的)会走下面sThreadLocal.set(new Looper(quitAllowed)),在Looper的初始化操作中会初始化MessageQueue,并且绑定当前线程(当前即为ui线程);
    #2 在loop()方法里会去获取当前Looper,并获取MessageQueue的实例,如果为null的话会有异常报出,然后遍历mQueue去拿到Message的引用msg,调用dispatchMessage(msg)(其实就是handler的dispatchMessage(msg))
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// prepareMainLooper() =>
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构造
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
// 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(); // might block
            //这里的msg.target指的就是handler
           msg.target.dispatchMessage(msg);
           msg.recycle();
    }
}

初始化Handler

  • 1)MainActivity.java
Handler mHandler = new Handler(){
      @Override
      public void handleMessage(Message msg) {
          super.handleMessage(msg);
      }
};
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      mHandler.sendEmptyMessageAtTime(1,1000);
}
  • 2 )Handler.java
    #1 在handler初始化方法里获取looper对象,通过looper对象回去mQueue,在mHandler.sendEmptyMessage()时,通过msg.target = this将当前handler绑定到message中,再通过获取到的mQueue.enqueueMessage()将当前message传入mQueue中
public Handler() {
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
}

// => sendEmptyMessageAtTime
 public boolean sendMessageAtTime(Message msg, long uptimeMillis){
    boolean sent = false;
    MessageQueue queue = mQueue;
    if (queue != null) {
        //这里其实就是把handler赋值给message.target
         msg.target = this;
         sent = queue.enqueueMessage(msg, uptimeMillis);
     } else {
          RuntimeException e = new RuntimeException(
          this + " sendMessageAtTime() called with no mQueue");
     }
     return sent;
}

// msg.target.dispatchMessage(msg); 接上边的looper
// handleMessage(msg) 创建handler时,复用的方法
public void handleMessage(Message msg) {
}
   

备注:handler机制的一些参考

转载于:https://www.jianshu.com/p/665c23fb9fbf