Handler基本用法:
主线程
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_WHAT:
Log.d(TAG, "main thread receiver message: " + ((String) msg.obj));
break;
}
}
};
private void sendMessageToMainThreadByWorkThread() {
new Thread(){
@Override
public void run() {
Message message = mHandler.obtainMessage(MESSAGE_WHAT);
message.obj = "I am message from work thread";
mHandler.sendMessage(message);
}
}.start();
}
非主线程:
new Thread(){
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//....
}
};
Looper.loop();
}
}.start();
Handler的主要四个类:
Handler、Message、MessageQueue、Looper。
Handler发送消息的简要流程:
(使用者)把将要发送的消息放入到Message中,Handler通过sendMessage()将Message发送到MessageQueue中。Looper不断调用loop()从MessageQueue中取出Message交给Handler处理,从而实现线程中的通信。
Handler内存泄漏:
原因:
创建Handler内部类的时候,Handler就隠式的持有activity的引用。当activity关闭的时候,线程的消息尚未发送,而线程持有Handler的引用,Handler又持有Activity的引用,所以造成了Activity无法被回收,导致内存泄漏。如果这操作来回多次,就会程序占用内存超过系统限制,FC(系统崩溃)。
解决办法:
在Activity关闭的时候,将Handler选在线程关掉或者调用Handler的removeCallBacksAndMessages(null)方法。
将Handler设为静态类,并且将Activity设为弱引用:
static class MyHandler extends Handler {
WeakReference<Activity > mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
Handler发送信息的唤醒机制:
A. Android应用程序的消息处理机制由消息循环、消息发送和消息处理三个部分组成的。
B. Android应用程序的主线程在进入消息循环过程前,会在内部创建一个Linux管道(Pipe),这个管道的作用是使得Android应用程序主线程在消息队列为空时可以进入空闲等待状态,并且使得当应用程序的消息队列有消息需要处理时唤醒应用程序的主线程。
C. Android应用程序的主线程进入空闲等待状态的方式实际上就是在管道的读端等待管道中有新的内容可读,具体来说就是是通过Linux系统的Epoll机制中的epoll_wait函数进行的。
D. 当往Android应用程序的消息队列中加入新的消息时,会同时往管道中的写端写入内容,通过这种方式就可以唤醒正在等待消息到来的应用程序主线程。
E. 当应用程序主线程在进入空闲等待前,会认为当前线程处理空闲状态,于是就会调用那些已经注册了的IdleHandler接口,使得应用程序有机会在空闲的时候处理一些事情。