Android消息机制

消息机制简介

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
public class MainActivity extends AppCompatActivity {
private final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//可以更新ui
System.out.println(msg.what);
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
//可以在此做耗时操作
Message message = Message.obtain();
message.what = 1;
handler.sendMessage(message);
}
}).start();
}
}

通常我们使用Handler的情景大概是这样的:在子线程中进行耗时操作,然后使用hanlder.sendMessage发送消息,在主线程中回调其handleMessage(Message msg)方法中进行更新ui.

组成

整个异步消息机制的完成需要4个部分:MessageQueue,Handler和Looper以及Message.

可以配合思维导图来分析源码

消息机制

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public final class Looper {
static final ThreadLocal<android.os.Looper> sThreadLocal = new ThreadLocal<android.os.Looper>();

final MessageQueue mQueue;
final Thread mThread;

private Looper(boolean quitAllowed) {
//创建一个 MessageQueue
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
//Looper.prepare()方法不能被调用两次,保证了一个线程中只有一个Looper实例
throw new RuntimeException("Only one Looper may be created per thread");
}
//将一个Looper的实例放入了ThreadLocal
sThreadLocal.set(new android.os.Looper(quitAllowed));
}


public static void loop() {
//获取sThreadLocal存储的Looper实例
final android.os.Looper me = myLooper();
if (me == null) {
//loop()应该在prepare()之后调用
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取到looper实例中的MessageQueue
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
//开始进入循环
for (; ; ) {
//取出消息 没有则阻塞
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
try {
//msg.target实际上为handler,即调用handler.dispatchMessage
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//释放msg资源
msg.recycleUnchecked();
}
}


public static Looper myLooper() {
return sThreadLocal.get();
}

}

总结:

  1. 绑定当前线程,保证线程中只有一个Looper,Looper中只有一个MessageQueue
  2. loop()方法会不断循环取出MessageQueue的Message,交给msg.target即handler.dispatchMessage()去处理.

Handler

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
public class Handler {
final android.os.Looper mLooper;
final MessageQueue mQueue;
final android.os.Handler.Callback mCallback;
final boolean mAsynchronous;

public interface Callback {
public boolean handleMessage(Message msg);
}

public void handleMessage(Message msg) {

}


// 5.
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//当Message存在回调方法,回调msg.callback.run()方法;
handleCallback(msg);
} else {
//当Handler存在Callback成员变量时,回调方法handleMessage();
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//Handler自身的回调方法handleMessage()
handleMessage(msg);
}
}


public Handler() {
this(null, false);
}

public Handler(android.os.Handler.Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends android.os.Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}

//1 获取当前线程保存的Looper实例
mLooper = android.os.Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//2 获取该looper的MessageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}


//各种sendMessage()方法最终都是调用此方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}



private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//3 将meg.target赋值为this,即Looper中loop()方法的msg.target.dispatchMessage(msg),msg.target实际上是handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//4 将msg加入MessageQueue
return queue.enqueueMessage(msg, uptimeMillis);
}

public final android.os.Looper getLooper() {
return mLooper;
}

private static void handleCallback(Message message) {
message.callback.run();
}

}

Looper是如何与Handler关联起来的?

Handler在构造中会调用Looper.myLoop(),实际上调用了Looper中sThreadLocal.get()方法获取保存的looper对象,sThreadLocal本质是个map, 在Looper.prepare方法中将key=Thread.currentThread value = looper 给保存在sThreadLocal中。至此,Looper和Handler关联起来了。

子线程中new Handler()

问: 为什么在主线程中直接new Handler()不会报错?

答: 在ActivityThread中的main方法已经调用了Looper.prepareMainLooper();

handler是无限循环而且在无消息时是阻塞的,为什么不会UI线程anr

ActivityThread是应用程序的入口,这里你可以看到写Java程序时司空见惯的main方法,而main方法正是整个Java程序的入口。

ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的程序也就可以退出了。

从消息队列中取消息可能会阻塞,取到消息会做出相应的处理。如果某个消息处理时间过长,就可能会影响UI线程的刷新速率,造成卡顿的现象。

来自知乎 大头鬼的回答:https://www.zhihu.com/question/34652589/answer/59558499

其他几种方式

  1. handler.post( )
  2. view.post( )
  3. runOnUiThread( )

上面三种方式都是直接或者间接的调用了handler.sendMessageAtTime()方法.具体源码就不再分析了