【Android自助餐】Handler消息机制完全解析(四)Looper解析
来源:互联网 发布:南昌大学怎么样知乎 编辑:程序博客网 时间:2024/05/29 13:21
Android自助餐Handler消息机制完全解析(四)Looper解析
- Android自助餐Handler消息机制完全解析四Looper解析
- Looper
- 初始化prepare
- 提供looper获取接口myLooper
- 处理消息队列loop
- Looper
Looper
如果你搞过Arduino,那么你肯定知道这个loop()
方法。没接触过也没关系,这个方法就是一个通过死循环来重复做某件事的方法。区别是Arduion的循环控制在loop()
方法外,而Looper
的循环控制在loop()
方法内。这个Looper
类本身则是对这个方法做了一些封装。
初始化prepare()
这里标题不是构造方法,因为其构造方法被private
修饰,那么来看看它什么时候调用了构造方法。很容易就能找到private static void prepare(boolean quitAllowed)
方法,该类仅在这里调用了构造方法,然而这个prepare()
也是被private
修饰的,那么来看看这个带参的prepare()
又在哪里被调用了。结果可以找到两个public static
修饰的方法:prepare()
和prepareMainLooper()
。
第一个方法原文说明如下:
Initialize the current thread as a looper.This gives you a chance to create handlers that then reference this looper, before actually starting the loop. Be sure to call
loop()
after calling this method, and end it by callingquit()
.
某以不才为诸君翻译如下:
作为looper初始化当前线程。提供一个机会来创建handler并使用looper。在使用之前,请在此方法之后调用
loop()
,并在结束时调用quit()
。
第二个方法原文说明如下:
Initialize the current thread as a looper, marking it as an application’s main looper. The main looper for your application is created by the Android environment, so you should never need to call this function yourself.
某再以不才为诸君奉上槽点:
作为looper初始化当前线程,并标记其为application主线程的looper。在application主线程中的looper被Android系统创建,因此开发者请永远不要手动调用这个方法。
不让掉还不让研究么,今天我们就看这个prepareMainLooper ()
干了点啥。先把源码放上来:
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); }}
首先调用了这个私有的带参的prepare()
方法并传了个false。这个私有方法声明为private static void prepare(boolean quitAllowed)
,因此判断该参数的含义是不允许退出。进来这个带参方法看看:
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
字段,类型是ThreadLocal
,先来看看该类的原文说明:
Implements a thread-local storage, that is, a variable for which each thread has its own value. All threads share the same
ThreadLocal
object, but each sees a different value when accessing it, and changes made by one thread do not affect the other threads. The implementation supportsnull
values.
某以不才:
实现一个线程本地存储,是什么呢?一个让每个线程都有拥有value的变量。所有的线程都共享同一个
ThreadLocal
对象,但每个线程在这拿到的value都不相同,并且一个线程在这里做的改变并不影响其他线程。支持值为null
。
如果理解不了可以类比一下View
类,该类有个setTag()
方法,用来让这个View携带附加值。此处的ThreadLocal
就是让线程可以携带附加值,因此也有get()
和set()
方法。两个方法中的第一句便是Thread.currentThread()
来获取当前线程,所以能看出上面那句“共享同一个对象”且“各线程互不影响”。
回到Lopper的带参prepare(),可以看到new了一个Lopper并放到当前线程的“tag”中,而此处是从prepareMainLopper()
进来的,因此当前线程便是主线程。
再看构造方法,里面只有两行代码:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}
创建了消息队列,并获取了当前线程。上文提到在Handler构造方法中有mQueue = looper.mQueue;
,说明Handler中的队列与Lopper中的队列是同一个队列。
到这里prepareMainLooper()
就执行完了,根据空参的prepare()
方法说明推断,“Android Environment”在调用prepareMainLooper()
后必然会调用loo()
。查看prepareMainLooper()
调用者可以看到,在SystemServer.run()
与ActivityThread.main()
中都在调用Looper.prepareMainLooper()
后不远就调用了Looper.loop()
。而这两处可以推断一个是系统应用的主线程,一个是用户应用的主线程。
提供looper获取接口myLooper()
prepare()
中提到了会将looper放到线程存储ThreadLocal
中,此处只需要从中取出并返回即可,因此代码只有一行return sThreadLocal.get();
。
处理消息队列loop()
先上核心源码:(有删减)
for (;;) { Message msg = queue.next(); if (msg == null) { return; } msg.target.dispatchMessage(msg); msg.recycleUnchecked();}
这里就一目了然了:一个死循环,不断从队列中取消息并分发,如果取到null就说明消息队列已经退出或被释放,此时loop终止。关于queue.next()
可以看MessageQueue的队列管理了解。msg.recycleUnchecked()
可以看Message中obtain()与recycle()的来龙去脉了解。msg.target.dispatchMessage(msg)
中target便是在Handler.obtainMessage()
时放到消息中的handler,dispatchMessage()
便是对消息的处理了。
- 【Android自助餐】Handler消息机制完全解析(四)Looper解析
- 【Android自助餐】Handler消息机制完全解析(三)Handler解析
- 【Android自助餐】Handler消息机制完全解析(一)Message中obtain()与recycle()的来龙去脉
- 【Android自助餐】Handler消息机制完全解析(二)MessageQueue的队列管理
- 【Android自助餐】Handler消息机制完全解析(五)鸟瞰与总结
- Android 消息机制,Looper、Handler、Message 解析
- android消息机制 - Handler、Looper原理解析
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue
- DLL注入技术之依赖可信进程注入
- [Ceph003]Ceph集群创建Cephfs文件
- 使用Iterator接口输出集合
- tomcat源码解析(五)--两种配置与异步servlet
- DLL注入技术之远线程注入
- 【Android自助餐】Handler消息机制完全解析(四)Looper解析
- Hdu 5344 MZL's xor (杂)
- 浅谈android网络编程
- java8之lambda总结
- Service解析
- DLL注入技术之消息钩子注入
- 读懂心经
- 【Android自助餐】Handler消息机制完全解析(五)鸟瞰与总结
- Consul 原理和使用简介