使用HandlerThread创建一个工作在新线程的Servic
2017-05-22 本文已影响44人
Bejamin
HandlerThread是Android API提供的一个便捷的线程类,使用它我们可以快速地创建一个带有Looper的线程,而这个Looper是和线程一对一绑定的。有了这个Looper之后,我们又可以生成工作在这个线程里面的Handler。
实现原理
在介绍原理之前,我们先用普通的Thread来创建一个Handler,过程大致如下:
Handler handler;
private void createMannualThreadWithHandler(){
new Thread(){
@Override
public void run(){
super.run();
Looper.prepare();
handler = new Handler(Looper.myLooper());
Looper.loop();
}
}.start();
}
实现很简单,需要在目标线程中做如下配置
- 调用Looper.prepare()创建与当前线程绑定的Looper实例
- 使用上面创建的Looper生成Handler实例
- 调用Looper.loop()实现消息循环
注意:
Looper.prepare()在一个线程中只能调用一次,否则会抛出异常;Looper.loop()方法是一个死循环,需要使用quit()/quitSafely()退出。
明白了上面的实现步骤,HandlerThread的实现也就简单了,源码如下:
@Override
public void run(){
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
Handler原理
理解Handler的原理,只需记住以下几点即可:
- Message意为消息,发送到Handler进行处理的对象,携带描述性的信息和数据。
- MessageQueue意为消息队列,Message的集合。
- Looper意为消息泵,用来从MessageQueue中抽取Message,发送给相应的Handler进行处理。
- Handler处理Looper抽取出来的Message。
如何使用
HandlerThread使用起来很容易,首先下以后进行初始化。
private Handler handler;
private LightTaskManager(){
HandlerThread workerThread = new HandlerThread("LightTaskThread");
workerThread.start();
handler = new Handler(workerThread.getLooper());
}
注意,上面的workerThread.start();
必须要先执行。
至于如何使用HandlerThread来执行任务,主要是调用Handler的API。
下面给出使用HandlerThread创建一个工作在新线程的Service组件。
使用HandlerThread创建一个工作在新的线程的Service组件的代码框架如下:
public class LDMService extends Service{
private HandlerThread ldmThread;
private LDMHandler ldmHandler;
final class LDMHandler extends Handler{
public LDMHandler(Looper looper){
// 将Handler和looper绑定
super(looper);
}
@Override
public void handleMessage(Message msg){
// TODO:处理消息的应用逻辑
}
}
@Override
public void onCreate(){
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
ldmThread = new HandlerThread("LDM Service Thread", Process.THREAD_PRIORITY_BACKGROUND);
ldmThread.start;
ldmHandler = new LDMHandler(ldmThread.getLooper());
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onDestroy(){
ldmThread.quitSafely();
}
}