[转载] 从Handler.post(Runnable r) ,Handler.sendEmptyMessage()梳理Android的消息机制(以及handler的内存泄露),
网友通过本文主要向大家介绍了[转载] 从Handler.post(Runnable r) ,Handler.sendEmptyMessage()梳理Android的消息机制(以及handler的内存泄露),等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
[转载] 从Handler.post(Runnable r) ,Handler.sendEmptyMessage()梳理Android的消息机制(以及handler的内存泄露),
Handler
每个初学Android开发的都绕不开Handler这个“坎”,为什么说是个坎呢,首先这是Android架构的精髓之一,其次大部分人都是知其然却不知其所以然。今天看到Handler.post这个方法之后决定再去翻翻源代码梳理一下Handler的实现机制。
异步更新UI
先来一个必背口诀“主线程不做耗时操作,子线程不更新UI”,这个规定应该是初学必知的,那要怎么来解决口诀里的问题呢,这时候Handler就出现在我们面前了(AsyncTask也行,不过本质上还是对Handler的封装),来一段经典常用代码(这里忽略内存泄露问题,我们后面再说):
首先在Activity中新建一个handler:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
mTestTV.setText("This is handleMessage");//更新UI
break;
}
}
};
然后在子线程里发送消息:
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);//在子线程有一段耗时操作,比如请求网络
mHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
至此完成了在子线程的耗时操作完成后在主线程异步更新UI,可是并没有用上标题的post,我们再来看post的版本:
private Handler mHandler;//全局变量
@Override
protected void onCreate(Bundle savedInstanceState) {
mHandler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);//在子线程有一段耗时操作,比如请求网络
mHandler.post(new Runnable() {
@Override
public void run() {
mTestTV.setText("This is post");//更新UI
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
从表面上来看,给post方法传了个Runnable,像是开了个子线程,可是在子线程里并不能更新UI啊,那么问题来了,这是怎么个情况呢?带着这个疑惑,来翻翻Handler的源码:
先来看看普通的sendEmptyMessage是什么样子:
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
将我们传入的参数封装成了一个消息,然后调用sendMessageDelayed:
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
再调用sendMessageAtTime:
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);
}
好了,我们再来看post():
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);//getPostMessage方法是两种发送消息的不同之处
}
方法只有一句,内部实现和普通的sendMessage是一样的,但是只有一点不同,那就是 getPostMessage(r) 这个方法:
private static Message getPostMessage(Runnable r) {