Android-0.Handler机制
文章目录
Handler机制类似于Window下的跨线程Post消息处理机制, 依赖于消息循环,入队,出队。
Android为什么要设置只能通过Handler机制更新UI?
假设如果在一个Activity中,有多个线程去更新UI,并且都没有加锁机制,马么会产生生么样的问题?——更新界面混乱;
如果对更新UI 的操作都加锁处理的话会产生什么样子的问题?——性能下降
对于上述问题的考虑,Android提供了一套更新UI的机制,我们只需要遵循这样的机制就好了。
不用关心多线程的问题,更新UI的操作,都是在主线程的消息队列当中轮询处理的。
Handler机制
大致流程为:Handler
在子线程中发送消息,消息会被添加到MessageQueue
消息队列中,再来由Handler
所处的当前线程的Looper
来不断的轮询MessageQueue
以获取出队消息,最后调用dispatchMessage
进行消息传递给handleMessage
进行处理。
基本使用方法
private static final int MSG_UPDATE = 100 ;
// 1.实例一个Handler对象(主线程)。
Handler mHander = new Handler(){
@Override
public void handleMessage(Message msg) {//3.handleMessage中接收处理(子线程消息发送到主线程中处理)。
if (MSG_UPDATE == msg.what){
// todo.
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {// 2.在子线程中使用Handler发送一个消息。
Message Msg = new Message();
Msg.what = MSG_UPDATE;
mHander.sendMessage(Msg);
}
}).start();
}
流程分析
1.实例一个Handler对象(主线程)。
public Handler(Callback callback, boolean async) {
......
mLooper = Looper.myLooper();
......
mQueue = mLooper.mQueue;
}
Handler拥有mLooper和mQueue,从这里可以得出如下关系:
Handler中拥有
Looper
和MessageQueue
,Looper
中拥有MessageQueue
,而且Handler
中的MessageQueue
来自于Looper
中的MessageQueue
。
那么这个Looper是如何实例化的?
安卓应用程序作为一个控制类程序,都是有一个入口的,而这个入口就是ActivityThread
的main
函数:
给Android Studio的onCreate
设置一个断点,断下,堆栈如下:
public static void main(String[] args) {
.....
Looper.prepareMainLooper();
.....
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
以上的main函数代码中,我们看到两点:
1.我们之所以可以在Activity用Handler handler=new Handler()
直接创建出来就默认绑定到主线程了,是因为上面的代码为我们做了绑定主线程的Looper
的事情。
2.主线程的Looper
是不能在程序中调用退出的,最后一句代码看到没,如果调用的话,就会抛出异常,退出主线程的循环是框架层在调用退出应用程序的时候才调用的。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {// 3.防止多次创建Looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));// 1.创建Looper,并设置到ThreadLocal中
}
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
.....
sMainLooper = myLooper();// 2.从ThreadLocal中取得创建的Looper
}
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Handler与Looper是成对出现的,一个子线程发送消息,一个主线程接收消息,那么这边就涉及到了多线程,线程之间的通讯,是需要保证数据的安全,即数据隔离,所以使用到了ThreadLocal进行线程管理:即A线程只能取得A线程的数据,而不能取得B线程的数据。
同时prepare的代码也表明了一个线程只能关联一个Looper对象
。
2.在子线程中使用Handler发送一个消息。
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
------------------------>
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
......
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
------------------------>
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
.....
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
------------------------>
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler的发送消息最终是通过它的mQueue
成员变量的.enqueueMessage
函数实现把消息添加到消息队列。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
3.handleMessage中接收处理(子线程消息发送到主线程中处理)。
前面提到
Handler中拥有
Looper
和MessageQueue
,Looper
中拥有MessageQueue
,而且Handler中的MessageQueue
来自于Looper中的MessageQueue
。
以及ActivityThread
的main
函数:
public static void main(String[] args) {
.....
Looper.prepareMainLooper();
.....
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
在 Looper.loop()
中不停的轮询:
/**
* 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();
.....
final MessageQueue queue = me.mQueue;
boolean slowDeliveryDetected = false;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
.......
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
msg.target.dispatchMessage(msg);
......
} finally {
}
.......
msg.recycleUnchecked();
}
}
内部调用了msg.target.dispatchMessage(msg)
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
转发到handleMessage