使用 HandlerThread 将loop转到子线程中处理分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅.
HandlerThread 其实也就是继承了Thread,并在run()方法内部执行Looper.prepare()和Looper.loop(),
既然Looper 是在子进程创建的,所以消息的处理也就是在子进程处理的.
我们如果创建 Handler 时使用HandlerThread 的Looper,那创建的Handler 对象处理消息时也就是运作在和 HandlerThread 一样的子进程了.
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
HandlerThread 有2个构造函数.
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
第一个构造函数默认是使用Process.THREAD_PRIORITY_DEFAULT ,这个的优先级比较高,容易导致和UI 进程抢cpu,一般使用THREAD_PRIORITY_BACKGROUND.
int THREAD_PRIORITY_AUDIO //标准音乐播放使用的线程优先级
int THREAD_PRIORITY_BACKGROUND //标准后台程序
int THREAD_PRIORITY_DEFAULT // 默认应用的优先级
int THREAD_PRIORITY_DISPLAY //标准显示系统优先级,主要是改善UI的刷新
int THREAD_PRIORITY_FOREGROUND //标准前台线程优先级
int THREAD_PRIORITY_LESS_FAVORABLE //低于favorable
int THREAD_PRIORITY_LOWEST //有效的线程最低的优先级
int THREAD_PRIORITY_MORE_FAVORABLE //高于favorable
int THREAD_PRIORITY_URGENT_AUDIO //标准较重要音频播放优先级
int THREAD_PRIORITY_URGENT_DISPLAY //标准较重要显示优先级,对于输入事件同样适用。
实例:如何让BroadcastReceiver 的onReceive 运行在子进程而不是main 进程
这里记录一种简单的方法,就是使用Context的下面的方法
public abstract Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler);
一般是注册广播接收器是这样写的:
context.registerReceiver(mBroadcastReceiver, filter);
但是这里需要使用上面带4个参数的registerReceiver方法.
其中String broadcastPermission 是可以null 的,关键在参数 Handler scheduler 上面.
在Handler scheduler 不为null 的时候,BroadcastReceiver 的 onReceive 就是运行在参数 Handler scheduler 所在的进程.
比如我们在一个activity 里面添加类似下面的代码:
HandlerThread handlerThread = new HandlerThread("HandlerThread_Broadcast");
handlerThread.start();
Handler broadcastHandler = new Handler(handlerThread.getLooper()) {
public void handleMessage(Message msg) {
//这里是可以做耗时操作的
mHandler.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
}
};
private final Handler mHandler = new Handler() {}
IntentFilter bootCompleteFilter = new IntentFilter();
bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
context.registerReceiver(mBroadcastReceiver, bootCompleteFilter,null,broadcastHandler);
比如上面的例子,mBroadcastReceiver 的 onReceive() 和 broadcastHandler handleMessage 是运行在HandlerThread_Broadcast 这个子进程的,但是 mHandler 还是在主进程里面.
类似用法还有ContentObserver的带参数的构造函数
public ContentObserver(Handler handler) {
mHandler = handler;
}