写点什么

Android Handler 源码浅析,一线互联网架构师筑基必备技能之 Android 篇

用户头像
Android架构
关注
发布于: 刚刚
  • 消息进队列 (总结)




上面流程走完,大家是不是很懵逼,mQueue 消息队列是啥玩意? mQueue初次相遇 应该是 sendMessageAtTime 方法:


public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {


MessageQueue queue = mQueue;


...


return enqueueMessage(queue, msg, uptimeMillis);


}


看起来是个成员变量,我们去成员变量找一下:


public class Handler {


...


final MessageQueue mQueue;


...


}


找找在哪里赋值的:


public Handler(@Nullable Callback callback, boolean async) {


...


mLooper = Looper.myLooper();


...


mQueue = mLooper.mQueue;


mCallback = callback;


mAsynchronous = async;


}


原来是在两个参数的构造方法中被赋值了,调用 Looper.myLooper() 拿到 mLooper,然后调用 mLooper.mQueue 方法,也就是说 mQueue 是 Looper 的一个成员变量。


以我们目前分析的源码,只知道我们把 Message 放入了 MessageQueue 中:



  • Looper 源码解析




Looper初次相遇 是在 Handler 两个参数的构造方法中,但是 Looper 并不是在这里创建的,那在哪里创建的呢?一切还要从盘古开天地说起:


在我们的程序启动后,经过一系列的启动流程,最终将会调用我们的 ActivityThread.java 这个类,这个类里面有个 main()方法,这个 main 方法大家一定不会陌生:


  • **ActivityThread#main**


ActivityThread 的 main()首先调用了 Looper.prepareMainLooper,初始化了 Looper


public static void main(String[] args) {


...


Looper.prepareMainLooper();


...


Looper.loop();


}


  • **Looper#prepareMainLooper**


调用了 prepare 并传入了 false


public static void prepareMainLooper() {


prepare(false);


synchronized (Looper.class) {


if (sMainLooper != null) {


throw new IllegalStateException("The main Looper has already been prepared.");


}


sMainLooper = myLooper();


}


}


  • **Looper#prepare**


这里 new 了一个 Looper,然后放进了 ThreadLocal 里面


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#Looper**


Looper 构造方法中初始化了一个 MessageQueue


private Looper(boolean quitAllowed) {


mQueue = new MessageQueue(quitAllowed);


mThread = Thread.currentThread();


}


  • ThreadLocal 是什么?


ThreadLocal 源码还是比较复杂的,所以我会专门写一篇文章来讲解,大家暂时理解为: 同一个 ThreadLocal 在不同的线程中 set 和 get 可以实现数据隔离,线程之间互不影响。比如 A 线程存入一个 1,B 线程存储一个 2,那在 A 线程中获取的值是 1,B 线程获取的值是 2


public class HelloThreadLocal {


public static void main(String[] args) {


ThreadLocal<Integer> threadLocal = new ThreadLocal<>();


new Thread(() -> {


threadLocal.set(1);


System.out.println(Thread.currentThread().getName()+": "+threadLocal.get());


},"线程 A").start();


new Thread(() -> {


threadLocal.set(2);


System.o


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ut.println(Thread.currentThread().getName()+": "+threadLocal.get());


},"线程 B").start();


}


}


执行结果:


线程 A: 1


线程 B: 2


  • **回到Looper#prepare**


现在我们学会了 ThreadLocal,再来看一遍这个代码,这里有一个判断,如果 ThreadLocal 获取的值不为空,就会抛出异常,否则就存储一个 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));


}


  • **回到ActivityThread#main**


上面我们已经分析完了 Looper.prepareMainLooper(),会创建一个 Looper 对象存到 ThreadLocal,现在我们看到 main()还执行了 Looper.loop()方法。


public static void main(String[] args) {


...


Looper.prepareMainLooper();


...


Looper.loop();


}


  • **Looper#loop**


loop 方法中的代码特别多,这里我们精简之后大概还剩这么多代码:


  1. 通过 myLooper()从 ThreadLocal 中拿到我们存放的 Looper 对象 me

  2. 从 me 中拿到 Looper 的消息队列 queue

  3. 创建一个死循环不停地从 queue 消息队列中取数据

  4. 如果数据为 null 就直接 return,如果有数据就调用 Handler 的 dispatchMessage 方法


public static void loop() {


final Looper me = myLooper();


...


final MessageQueue queue = me.mQueue;


...


for (;;) {


Message msg = queue.next();


if (msg == null) {


return;


}


...


msg.target.dispatchMessage(msg); //如果消息不等于 null,就会走这里


}


...


}


  • **Handler#dispatchMessage**


如果消息队列循环不等于 null,就会走这个方法,然后调用 handleMessage(msg)


public void dispatchMessage(@NonNull Message msg) {


if (msg.callback != null) {


handleCallback(msg);


} else {


if (mCallback != null) {


if (mCallback.handleMessage(msg)) {


return;


}


}


handleMessage(msg);


}


}


  • **Handler#handleMessage**


这个方法是一个空实现,最终由用户定义的 Handler 子类实现。


public void handleMessage(@NonNull Message msg) {


}


  • **自己的定义的Handler#handleMessage**


会回调到我们自己的 Handler 的 handleMessage 方法,并传回 Message


private Handler mHandler = new Handler() {


@Override


public void handleMessage(Message msg) {


super.handleMessage(msg);


Log.d("lkx", (String) msg.obj);


}


};


大概流程好像是走通了…


  • 总结




用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android Handler源码浅析,一线互联网架构师筑基必备技能之Android篇