版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pihailailou/article/details/78838246
一,写在前面
IntentService使用场景:需要在服务中执行耗时的任务,使用IntentService代替在Service中开启子线程。
HandlerThread:封装了Thread+Looper,但并没有封装Handler。它是一个线程,run方法中初始化了Looper对象,并开启消息循环。
IntentService:封装了HandlerThread+Handler的Service。
在阅读本篇文章前,建议先了解Handler机制的工作原理,本篇将不再对重复内容进行阐述。可参考文章
二,使用IntentService
直接上代码,IntentService是一个抽象类,首先创建一个它的子类:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
SystemClock.sleep(3000);
String stringExtra = intent.getStringExtra("key");
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:MM:ss");
String time = format.format(new Date(System.currentTimeMillis()));
Log.e("wcc", "onHandleIntent _ " + stringExtra + ", time is " + time);
}
@Override
public void onCreate() {
super.onCreate();
Log.e("wcc", "onCreate");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.e("wcc", "onStart");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("wcc", "onDestroy");
}
}
接下来是启动服务的代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra("key", "value1");
startService(intent);
intent.putExtra("key", "value2");
startService(intent);
}
}
启动了两次服务,每次存储在extra中的值都不一样。在onHandleIntent方法中执行耗时操作,并在各个生命周期方法中打印log。
打印log如下:
启动两次服务,onStart调用两次,onHandleIntent方法被调用两次且间隔3秒,最后onDestroy也被调用。为了解释上面这一现象,下面开始从源码角度分析IntentService工作原理。
三,HandlerThread源码分析
public class HandlerThread extends Thread {
//...code
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
//...code
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();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
//...code
}
第8行,初始化Looper对象,并使用ThreadLocal存储该子线程的Looper。
第10行,从ThreadLocal中取出该线程的Looper对象,并赋值给变量mLooper。
第15行,调用Looper.loop()方法开启消息循环。
第21行,调用HandlerThread$getLooper返回变量mLooper,也就是获取该线程的Looper对象。
(对ThreadLocal,Looper不了解可以查看前面推荐的参考文章,这里不再重复描述)
小结:从上面可以看出,HandlerThread并不像名称展现的那样,它并没有封装Handler,而是封装了Thread,Looper。也就是说,HandlerThread是一个开启了消息循环的子线程。
注意:使用HandlerThread时,若不需要HandlerThread的时候,可以调用HandlerThread的quit/quitSafely方法结束消息循环,从而终止线程的执行。关于结束消息循环的原理,见文章
Android中Looper,MessageQueue,ThreadLocal源码解析 ,这里不再重复阐述。
四,IntentService源码分析
在调用startService启动服务的时候,会调用onCreate,onStart方法。
查看IntentService$onCreate,IntentService$onStart方法相关的源码:
@Override
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);
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
第8行,创建HandlerThread对象,它是一个开启了消息循环的子线程。
第9行,调用HandlerThread$start方法启动线程,HandlerThread$run方法被调用,前面已对该方法进行分析,这里不再重复阐述。
第11行,获取HandlerThread中的Loooper对象,是一个子线程中的Looper对象。
第12行,创建一个变量mServiceLooper构造的Handler对象。
第17~19行,创建Message对象并设置字段arg1,obj的值;
第20行,使用Handler$sendMessage方法发送消息;
于是,查看ServiceHandler对消息的处理,查看其源码:
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);
}
}
第3行,调用Handler中Looper为参数的构造函数;
第8行,调用IntentService$onHandleIntent方法;
第9行,调用IntentService$stopSelf方法,停止服务,回调onDestroy方法。
查看IntentService$onHandleIntent方法源码:
protected abstract void onHandleIntent(Intent intent);
onHandleIntent是一个抽象方法,需要我们自己重写该方法,并将耗时操作放在里面。
那么onHandleIntent为啥能执行耗时操作呢?
通过对Handler机制的理解可以知道:调用Looper$loop方法取出消息队列里的消息,并处理消息。因此消息的处理在哪个线程中完成取决于Looper.loop()在哪被调用,前面我们知道Looper的初始化,以及开启消息循环都是在子线程HandlerThread的run方法中完成。于是消息的处理是在子线程中执行,onHandleIntent就可以执行耗时操作。
五,最后
可以发现IntentService通过Handler机制将任务的执行,由主线程切换到Looper所在的子线程中执行。
若调用多个startService启动多个耗时任务,由于内部实现基于Handler机制,Looper是按照顺序来处理消息,因此这些耗时任务将按照启动的顺序依次执行。
另外,在handleMessage方法里调用stopSelf(startId)来停止服务,此外还有一个重载方法stopSelf()。区别:stopSelf(startId)停止服务,会等待消息队列里的消息全部处理完毕,再停止服务;而stopSelf()会立刻停止服务。
扫描二维码关注公众号,回复:
3319950 查看本文章