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

Android源码分析之Handler消息机制

程序员文章站 2022-07-14 15:05:54
...

 


前言

随着Android的不断发展,越来越多的开发者开始对源码开始研究,Handler作为子线程的重要成员,下面让我们一起进行源码学习。


 

一、Handler是什么?

   在Android开发中,Handler主要被用来进行耗时操作,消息处理等,大家都知道在主线程中进行耗时操作或者IO读写,会引发ANR异常,所以Android引入Handler来开启子线程进行耗时操作和IO读写,等处理完,Handler将处理结果返回给主线程进行展示。

二、Handler包括哪些部分

1.Looper

在Handler的构造器中:

public Handler(@Nullable Callback callback, boolean async) {
   
   xxxxx
   xxxxx
   省略代码.....  
  
    mLooper = Looper.myLooper(); //在创建Handler时默认获取一个mLooper
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");  //Looper不能为空,否则报运行时异常
    }
    mQueue = mLooper.mQueue;//通过mLooper获取一个消息队列mQueue
    mCallback = callback;
    mAsynchronous = async;
}
由此可见,当我们创建Handler的时候,Handler已经为我们准备好了一个不为空的Looper。

进入到Looper中。在Looper的构造器中,初始化了MessageQueue,并获取当前的线程。

 private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed); //消息队列
        mThread = Thread.currentThread(); //获取当前线程
    }

在系统调用Looper的prepare方法时,先判断sThreadLocal中是否存在looper,如果存在即报运行时异常,threadLocal通过存储当前线程里的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));
    }

通过sThreadLocal来获取当前线程的looper
public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

2.Message

Message是信息的主要载体,通过Message来传递不同的数据。 通过源码得知,Message实现来Parcelable序列化接口。

public final class Message implements Parcelable  
public static final Object sPoolSync = new Object(); //同步对象锁
private static Message sPool; //消息池

从全局池返回一个新的Message实例。使我们在许多情况下避免分配新对象

public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
 return new Message();
}

Message通过target来保存当前创建的handler对象,

public static Message obtain(Handler h) {
    Message m = obtain();
    m.target = h;

    return m;
}

3.MessageQueue

MessageQueue 消息队列,用来存储信息。

 


总结

Handler消息机制需要MessageQueue和Looper支撑,Handler中Looper在初始化时会创建消息队列和获取当前线程。Looper通过ThreadLocal存储,确保可以为不同的线程提供不同的数据信息。