1. Looper的简单介绍
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| /**
* Class used to run a message loop for a thread. Threads by default do
* not have a message loop associated with them; to create one, call
* {@link #prepare} in the thread that is to run the loop, and then
* {@link #loop} to have it process messages until the loop is stopped.
*
* <p>Most interaction with a message loop is through the
* {@link Handler} class.
*
* <p>This is a typical example of the implementation of a Looper thread,
* using the separation of {@link #prepare} and {@link #loop} to create an
* initial Handler to communicate with the Looper.
*
* <pre>
* class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
*
* Looper.loop();
* }
* }</pre>
*/
public final class Looper {
/*
* API Implementation Note:
*
* This class contains the code required to set up and manage an event loop
* based on MessageQueue. APIs that affect the state of the queue should be
* defined on MessageQueue or Handler rather than on Looper itself. For example,
* idle handlers and sync barriers are defined on the queue whereas preparing the
* thread, looping, and quitting are defined on the looper.
*/
}
|
- 先看到Looper的定义和官方的注释介绍,Looper要运行在一个thread中,但是thread默认是和Looper没有关系的,需要在thread里调用
Looper.prepare();
以及Looper.loop();
官方并在注释里给出了使用的demo代码,但是更推荐直接使用HandlerThread这个类 - Looper这个类的作用是循环事件,响应队列状态的API应该是被定义在MessageQueue或者Handler里,而不是在Looper自身,例如同步屏障和空闲状态都是被定义在队列里,而准备线程,循环,退出操作则定义在Looper中
2. Looper的构造方法
1
2
3
4
| private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
|
可以看到构造方法是私有的,而且只做了构建一个MessageQueue和获得当前的thread
3. Looper.prepare()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| /** 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
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
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));
}
|
看到源码就可以理解官方的注释demo里为何第一步要调用prepare()方法,先通过sThreadLocal来判断当前线程下是否有一个Looper,如果有,则抛出异常,如果没有则new出一个属于当前线程的Looper,因此从代码可知,每一个线程里只可能有一个Looper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| /**
* 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. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
|
prepareMainLooper和prepare差不多,prepareMainLooper是在ActivityThread的main中调用的,是应用创建时候调用了一次,创建了主线程的Looper,所以开发者不能主动调用此方法
4. 获得已有的Looper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| /**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
|
- myLooper()则是通过当前线程来获取Looper,而getMainLooper()则是因为在prepareMainLooper()中单独保存了主线程的Looper,所以可以直接返回,但实际上在主线程下使用myLooper()一样能拿到主线程的Looper
- 通常获取到Looper是用来传入构建新的Handler
5. Looper.loop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| /**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the 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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
/**
*省略
*/
try {
msg.target.dispatchMessage(msg);
} finally {
/**
*省略
*/
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
|
- 在开始loop前先获取当前线程下的Looper,如果为null,那么就是当前线程下prepare()并没有调用,抛出异常
- 通过queue.next()获得msg为null,则queue退出,那么Looper的死循环也要退出
- 调用获得的msg拿到对应的handler,并调用dispatchMessage,最终调用到handleMessage实现,完成了一次从发送msg到处理msg的过程
- 最后msg进行回收