HandlerThread和IntentService,使用场景较少,但有些特定的场景会比较好用。
顾名思义HandlerThread,本质上是一个Thread,IntentService,本质上是一个Service,只是继承了Thread和Service类之后,它们内部做的一些动作使得这两个类不太一样,接下来我们来分析一下具体用法和源码:
一、HandlerThread
1、使用
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
Log.d(TAG,"what : " + msg.what);
Log.d(TAG,"thread : " + Thread.currentThread());
super.handleMessage(msg);
}
};
Message message = handler.obtainMessage();
message.what = 1;
handler.sendMessage(message);
首先创建一个HandlerThread的实例,并传入一个String类型的参数,作为线程的名字,然后新建一个Handler,把handlerThread.getLooper()作为参数传入Handler的构造参数。我们知道Handler需要一个Looper来构建消息循环,主线程的Handler使用的是sMainLooper,而如果我们要在子线程里面使用Handler,就要自己构建Looper,进行Looper.prepare()以及Looper.Loop(),这里HandlerThread正是起了一个创建Looper环境的作用,通过打印也可以看到:
12:55:00.905 4045-4062/com.optoma.imagetest D/MainActivity: what : 1
thread : Thread[MyHandlerThread,5,main]
当前线程是HandlerThread创建的MyHandlerThread线程。
2、源码分析
HandlerThread的源码较为简单,首先有两个构造参数,可以传入线程名,以及线程优先级,线程名不用赘述,线程优先级是给CPU调度线程的运行顺序的一个参考。往下看,我们能看到一个onLooperPrepared()方法:
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
通过注释可以看到,这个方法是给我们继承HandlerThread,然后在loop()之前做的一些操作,比如一些数据的初始化等。再往下看,重写了run()方法:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();//Looper准备
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();//这里是为了避免getLooper()在没初始化之前就调用,得到一个空值
}
Process.setThreadPriority(mPriority);//设置进程优先级
onLooperPrepared();//
Looper.loop();//开始循环
mTid = -1;
}
里面就是一个Looper的准备以及循环过程,getLooper()方法的代码如下:
public Looper getLooper() {
if (!isAlive()) {
return null;//线程不在活动状态,返回空
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();//一直等到mLooper不为空才notify()
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
HandlerThread代码较少,有些时候可以用到,比如需要在子线程处理数据,然后再发信息到主线程更新UI等。
二、IntentService
1、使用
IntentService作为一个Service,有着独特的使用场景。一般使用需要继承IntentService这个抽象类:
然后重写onHandleIntent()方法即可。
IntentService的特点是:在onHandleIntent()方法执行完毕之后,会销毁Service,即StopSelf(),所以我们可以在一些类似于文件扫描等场景下使用,不需要关注它的生命周期,文件扫描完成之后会自动关闭
2、源码分析
IntentService的代码内部,我们可以看到HandlerThread的影子
首先从构造函数,IntentService接受一个String类型的name,其实也是作为线程的名字:
我们可以看到一个Handler
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
然后发现在IntentService的onCreate方法里面,有对这个Handler的调用:
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
这下就很清楚了,传入的name,作为"IntentService[" + mName + "]"来给线程命名,这里使用到了HandlerThread来创建Looper,并构建Handler,然后在onStart方法中传递消息:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
onStart里面只有几行代码,即传输startId和intent到ServiceHandler,ServiceHandler开始调用onHandleIntent()方法,startId用来stopSelf,而intent则用来传递给onHandleIntent()。
从这里不难看出,IntentService的onHandleIntent方法,其实也是运行在子线程的,所以可以做一些占内存的事而不用担心主线程被阻塞,这也是使用HandlerThread的原因。
三、拓展
多个IntentService的情况:
我们写一个简单的例子,在MainActivity中启动多次Service,然后重写Service的方法,看最终的打印:
Handler handler = new Handler();
for (int i = 0; i < 5; i++) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(MainActivity.this,MyIntentService.class);
startService(intent);
}
}, 100);
}
public class MyIntentService extends IntentService {
private static final String TAG = MyIntentService.class.getSimpleName();
private int count = 0;
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent : " + count++);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand : " + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Log.d(TAG, "onStart : " + startId);
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}
最终得出的结果:
10-09 13:34:34.914 23354-23354/? D/MyIntentService: onCreate
10-09 13:34:34.915 23354-23354/? D/MyIntentService: onStartCommand : 1
onStart : 1
10-09 13:34:34.932 23354-23354/? D/MyIntentService: onStartCommand : 2
onStart : 2
10-09 13:34:34.933 23354-23354/? D/MyIntentService: onStartCommand : 3
onStart : 3
10-09 13:34:34.934 23354-23354/? D/MyIntentService: onStartCommand : 4
onStart : 4
10-09 13:34:34.935 23354-23354/? D/MyIntentService: onStartCommand : 5
10-09 13:34:34.952 23354-23354/? D/MyIntentService: onStart : 5
10-09 13:34:35.917 23354-23391/com.optoma.imagetest D/MyIntentService: onHandleIntent : 0
10-09 13:34:36.918 23354-23391/com.optoma.imagetest D/MyIntentService: onHandleIntent : 1
10-09 13:34:37.919 23354-23391/com.optoma.imagetest D/MyIntentService: onHandleIntent : 2
10-09 13:34:38.920 23354-23391/com.optoma.imagetest D/MyIntentService: onHandleIntent : 3
10-09 13:34:39.980 23354-23391/com.optoma.imagetest D/MyIntentService: onHandleIntent : 4
10-09 13:34:39.980 23354-23391/com.optoma.imagetest D/MyIntentService: onDestroy
可以看出onCreate只会调用一次,但是onStartCommand以及onStart会调用多次,onHandleIntent则会一一执行,直到所有都执行完毕,最终调用onDestroy方法。上面看到的onHandleIntent之后调用的stopSelf(int startId)没有终止服务的原因是:stopSelf()会立即停止服务,而stopSelf(int startId)会等待所有消息都处理完后才终止服务。