Handler机制是Android中最神奇的机制之一
主要应用:
1. 定时、延迟执行
2. 跨页面传递数据发起事件
3. 跨线程执行
Handler机制分为:Handler、Loop、MessageQueue、Message四个类
关系:一个Thread对应一个Loop,一个Loop对应一个MessageQueue,一个MessageQueue对应多个Message,一个Message对应一个Handler
Handler关系类图:
Handler运行流程图:
Question:
1.子线程是如何将runnable post到主线程运行的?
答:其实在自线程中运行runnable.post方法,真正的作用:
1. Message.obtion一个Message
2. Message.callback = runnable ,将runnable赋值给message的callback变量
3. 执行了MessageQueue.enqueueMessage方法,将此Message添加到Message通过next指针构成的列表头部(或者头部第二个)
4. 调用nativeWake(mPtr);通知MessageQueue中的nativePollOnce(ptr, nextPollTimeoutMillis);苏醒
5. 继续在他之前运行的线程中(这里是主线程)运行next()抓取Message,交给Looper.loop
6. loop调用Message对应Handler的dispatchMessage方法
7. 调用Handler的handleCallback方法
8. 最终执行message.callback.run()
最终在主线程中跑完了这个runnable方法
2.Looper.looper()、MessageQueue.next为何不会阻塞?
答:其实流程图已经给出了答案:
MessageQueue.next()方法会调用nativePollOnce(ptr, nextPollTimeoutMillis);进行休息,让本线程的其它逻辑先运行,发现有新的Message通过MessageQueue的enqueueMessage()方法添加,会调用nativeWake(mPtr);通知nativePollOnce(ptr, nextPollTimeoutMillis);苏醒继续执行。运行结束之后又会继续休息,循环往复
3.handler为何会导致内存泄漏?如何避免?
答:handler可以通过xxxdelay()方法,延迟dispatchMessage运行,如果在等待的这段时间相应Activity关闭掉,那么之前发出去的message内部还通过target持有handler对象,而handler为activity的内部成员,所以这段时间内activity会因为内部成员handler无法被释放而无法释放内存,故这段时间内会导致内存泄漏。
解决办法:handler.removeCallbacksAndMessages(null);
会调用MessageQueue的removeCallbacksAndMessages方法
内部的逻辑是如果参数为null,那么会调用当前线程所有的Message的recycleUnchecked方法,此方法会将内部所有变成置空,等待垃圾回收器回收。
4.message为何不会分发到错误的handler?
答:因为每个Message有一个target变量指定了其所需要运行的Handler
5.子线程如何创建并使用handler?
package com.test.looper;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class MainActivity extends Activity {
private LooperThread looperThread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
looperThread = new LooperThread();
looperThread.start();
looperThread.getHandler().sendEmptyMessage(1);
}
class LooperThread extends Thread {
private Handler mHandler;
private final Object mSync = new Object();
public void run() {
// 自线程中需要手动Looper.prepare以及手动loop
// 需要注意的是:在创建Handler之前需要先执行Looper.prepare
Looper.prepare();
synchronized (mSync) {
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Log.d("CYQ", "--->" + msg);
}
};
mSync.notifyAll();
}
Looper.loop();
}
public Handler getHandler() {
synchronized (mSync) {
if (mHandler == null) {
try {
mSync.wait();
} catch (InterruptedException e) {
}
}
return mHandler;
}
}
public void exit() {
getHandler().post(new Runnable(){
public void run() {
Looper.myLooper().quit();
}});
}
}
}
面试中还有时候会问:如何实现主线程向子线程发送消息?(上面的代码就是答案)
其实了解Handler机制之后,道理都一样的:
仅仅是在主线程中调用自线程的handler,发送消息,子线程自己会通过MessageQueue.next方法跑子线程的message
自己写了个Handler工具类,方便各线程获取自己线程的Handler、主线程的Handler:
/**
* Handler帮助类
*
* @author yuanyang
*
*/
public class HandlerUtils {
private HandlerUtils() {
}
private static class Holder {
public static HandlerUtils instance = new HandlerUtils();
}
public static HandlerUtils getInstance() {
return Holder.instance;
}
private Handler mHandler;
/**
* 获取新Handler,子线程没有Looper就用主线程的Handler
*/
public Handler getNewHandler() {
Looper myLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
if (myLooper == null) {
mHandler = new Handler(mainLooper);
} else {
mHandler = new Handler(myLooper);
}
return mHandler;
}
/**
* 获取新Handler,子线程没有Looper就用主线程的Handler
*/
public Handler getNewHandlerCB(final HandlerDispose hd) {
Looper myLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
if (myLooper == null) {
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
} else {
mHandler = new Handler(myLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
}
return mHandler;
}
/**
* 获取子线程Handler
*/
public Handler getNewChildHandler() {
Looper myLooper = Looper.myLooper();
if (myLooper == null) {
Looper.prepare();
mHandler = new Handler(Looper.myLooper());
Looper.loop();
} else {
mHandler = new Handler(myLooper);
}
return mHandler;
}
/**
* 获取子线程Handler
*/
public Handler getNewChildHandlerCB(final HandlerDispose hd) {
Looper myLooper = Looper.myLooper();
if (myLooper == null) {
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
Looper.loop();
} else {
mHandler = new Handler(myLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
}
return mHandler;
}
/**
* 获取UI线程Handler
*/
public Handler getUIHandler() {
// 若成员变量Handler为
if (mHandler != null) {
if (mHandler.getLooper() == Looper.getMainLooper()) {
return mHandler;
}
}
Looper mainLooper = Looper.getMainLooper();
mHandler = new Handler(mainLooper);
return mHandler;
}
/**
* 获取UI线程Handler
*/
public Handler getUIHandlerCB(final HandlerDispose hd) {
Looper mainLooper = Looper.getMainLooper();
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
hd.handleMessage(msg);
}
};
return mHandler;
}
/**
* UI界面关闭的时候清空Handler,方式内存泄漏
*/
public void UIOnFinish() {
mHandler = null;
}
/**
* Handler的回调接口
*
* @author yuanyang
*
*/
public interface HandlerDispose {
public void handleMessage(android.os.Message msg);
}
}