IntentService 是继承自 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,当任务执行完后,IntentService 会自动停止,不需要我们去手动结束。
如果启动 IntentService 多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,依次去执行,执行完自动结束。
正常来讲,一个服务可写成这样
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// do something耗时
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
......
}
这种服务一旦启动就会处于运行状态,必须调用stopService或者stopSelf停止,如果想要实现执行完毕自动停止功能,可以写成
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// do something耗时
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
......
}
为了简化这种start、stop操作,Android提供了IntentService类。
-
- 必须在内部调用父类有参构造函数
-
- 子类实现onHandleIntent,处理具体逻辑
public class MyIntentService extends IntentService {
public MyIntentService() {
// 1. 必须在内部调用父类有参构造函数
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// 2. 子类实现onHandleIntent,处理具体逻辑
}
}
原理
IntentService封装了HandlerThread和Handler。当IntentService被第一次启动时,它的onCreate()方法会被调用,onCreat()方法会创建一个HandlerThread,然后使用它的Looper来构造一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息最终都会在HandlerThread中执行。
生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至onStartCommand()方法的Intetnt。
生成一个工作队列来传送Intent对象给onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。在所有的请求(Intent)都被执行完以后会自动停止服务,所以,不需要自己去调用stopSelf()方法来停止。
该服务提供了一个onBind()方法的默认实现,它返回null。
提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent做相应的处理。
为什么在mServiceHandler的handleMessage()回调方法中执行完onHandlerIntent()方法后要使用带参数的stopSelf()方法?
因为stopSel()方法会立即停止服务,而stopSelf(int startId)会等待所有的消息都处理完毕后才终止服务,一般来说,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务,不相等则不停止服务。
HandlerThread
1、HandlerThread原理
当系统有多个耗时任务需要执行时,每个任务都会开启个新线程去执行耗时任务,这样会导致系统多次创建和销毁线程,从而影响性能。
为了解决这一问题,Google提出了HandlerThread,HandlerThread本质上是一个线程类,它继承了Thread。HandlerThread有自己的内部Looper对象,可以进行loopr循环。通过获取HandlerThread的looper对象传递给Handler对象,可以在handleMessage()方法中执行异步任务。创建HandlerThread后必须先调用HandlerThread.start()方法,Thread会先调用run方法,创建Looper对象。当有耗时任务进入队列时,则不需要开启新线程,在原有的线程中执行耗时任务即可,否则线程阻塞。它在Android中的一个具体的使用场景是IntentService。
由于HanlderThread的run()方法是一个无限循环,因此当明确不需要再使用HandlerThread时,可以通过它的quit或者quitSafely方法来终止线程的执行。
2、HanlderThread的优缺点
优点: 异步不会堵塞,减少对性能的消耗。
缺点:不能同时继续进行多任务处理,要等待进行处理,处理效率较低。
HandlerThread与线程池不同,HandlerThread是一个串队列,背后只有一个线程。
HandlerThread 与 多线程线程池的区别
Handlerthread可以实现异步处理消息,还是批量的。多线程也是异步,处理批量消息。那么这两者的区别呢。
想了想,其实这两者的区别是很大的,多线程注重的并发,可以有多个线程,或者引入线程池进行管理。但是HandlerThread如果是new 一个,那么它就是一个线程,一个线程处理多个消息。
还有一个区别,handlerthread的run方法里面是死循环,也就是除非手动调用quit方法线程是不会退出的,而多线程的线程有各自的处理方式,没有固定。
所以,我认为handlerthread适合后台处理一些零散的消息,他的存活周期由你决定。而多线程更注重并发,当然也要考虑实际资源情况,用线程池的话也可以达到后台批处理消息,各种消息,当然开销会大一些。