IntentService源码分析

出现原因,使用,优势

出现原因:
服务中的逻辑都是运行在主线程中的,如果我们想要执行耗时的操作,需要自己手动的开启线程,同时当任务执行结束后,需要手动的调用stopSelf或者stopService方法终止服务的运行。为了方便开发者进行开发,提供了IntentService。

使用
IntentService是一个抽象类,是Service的子类,使用IntentService只需要创建一个类继承IntentServive,然后重写其onHandleIntent方法即可。

优势
onHandleIntent方法是运行在子线程中的,我们可以在其中执行耗时的操作,当操作执行完毕后,IntentService会自动的结束运行。使用Intentservice免去了我们手动开启线程和关闭服务的过程,方便了开发。除了可以省去手动的创建线程,关闭服务的步骤之外,IntentService还有另一个优势,那就是由于IntentService是一个服务,所以IntentService的优先级比单纯的线程高,不容易被系统杀死,所以可以利用IntentService执行一些优先级比较高的后台任务。

源码分析

IntentService内部封装了HandlerThread和Handler,从onCrete方法可以看出:

1
2
3
4
5
6
7
8
9
10
11
12
13
@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);
}

onCreate方法中创建了HanlerThread同时获取创建的HandlerThread的内部的Looper,利用获取到的Looper创建了一个ServiceHandler对象。

每次启动IntentService的时候,他的onStartCommand方法就会被调用,在onStartCommand方法中调用了onStart方法,源码如下:

1
2
3
4
5
 @Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

1
2
3
4
5
6
7
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

onStart方法中只是利用在onCreate方法中创建的ServiceHandler对象创建并且发送了消息,最终发送的消息会在ServiceHandler的handleMessage方法中被处理。

1
2
3
4
5
6
7
8
9
10
11
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);
}
}

ServiceHandler是IntentService的内部类,是Handler的子类,重写了其handleMessage方法,在handleMessage方法中调用了onHandleIntent方法处理消息,同时调用了stopSelf方法终止IntentService的运行。

onHandleIntent是IntentService的一个抽象方法,需要我们在子类中实现,onHandleIntent中接收到的参数Intent和启动IntentServie的时候startService(intent)的intent是相同的,我们可以从其中解析出启动Service的时候所传递进来的参数,从而对不同的任务作出去区分,对不同的任务进行不同的处理。

当onHandleIntent执行结束后,会执行stopSelf(int startId)来尝试停止服务,之所以使用stopSelf(int startId)方法而不是使用stopSelf方法来停止服务,是因为stopSelf方法会立即终止服务,而此时可能会有其他消息还没有被处理。stopSelf(int startId)方法会等所有的消息被处理了之后才终止服务的运行。如果当前只有一个后台任务,那么
stopSelf(int startId)会立即终止服务,如果由多个后台任务,会等所有的后台任务运行完后,终止服务。

从之前对Android的消息机制的分析我们可以知道,Handler的handleMessage方法最终会在Hanler所对应的Looper的loop方法中被调用,也就是说会在Looper所在的线程中被调用。由于创建ServiceHandler的时候传递进去的是HandlerThread的Looper,所以最终的handleMessage方法会在HandlerThread的run方法中被调用,这也就是为什么我们可以在onHandleIntent中执行耗时操作的原因。

此外还有一点需要注意,每次启动一个任务,都需要启动IntentService,而IntentService内部是通过消息的形式的请求任务的执行的,而Handler的Looper是顺序的处理任务的,所以IntentService也是顺序的处理任务的。

最后还有一个setIntentRedelivery方法需要讲解:

1
2
3
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}

mRedelivery的值将影响onStartCommand的返回结果,如果mRedelivery设置为true,那么onStartCommand将返回START_REDELIVER_INTENT;如果为false,将返回START_NOT_STICKY。

onStartCommand返回的结果将影响IntentService异常终止情况下重启服务时的行为,默认情况下,当IntentService因为系统内存吃紧或者其他原因被异常终止时,系统不会尝试重新启动服务,这时,如果IntentService#onStartCommand方法返回。

START_NOT_STICKY:服务不会重新创建,除非你再次调用startService
START_REDELIVER_INTENT:服务重新创建并启动,依次回调onCreate,onStartCommand,并且会把最后一次传给此服务的intent重新发给onStartCommand,也就是说如果有大量的intent投递了,那么只保证最近的intent会被重投递。。

由此我们可以发现,当我们的操作不是十分重要的时候,我们可以选择START_NOT_STICKY,这也是IntentService的默认选项,当我们认为操作十分重要时,则应该选择START_REDELIVER_INTENT 型服务。

建议阅读:Service#onStartCommand返回值解析
Service类onStartCommand()返回值讲解.

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class  MyService extends IntentService {


private static final String TAG = "MyService";

public MyService() {
super(TAG);
}


@Override
protected void onHandleIntent(@Nullable Intent intent) {
SystemClock.sleep(1000);
Log.d(TAG,"::::name::::"+intent.getStringExtra("name"));
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}

IntentService串行示例

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器