概述
本文记录 IntentService 的使用方式,以及可能产生的问题.
IntentService
关于IntentService本身的使用很简单,官方的解释也说的很清楚。IntentService是Service类的子类,用来处理异步请求。和正常启动一个Service一样,可以通过startService(Intent)方法启动一个IntentService,同时通过Intent传递数据。IntentService在onCreate()函数中通过HandlerThread开启一个线程来处理Intent请求对象,这样就可以在非主线程执行任务。这里处理消息的时候,也是通过为新创建的线程新建了Handler和Looper对象从消息队列中取出消息进行执行。处理每个Intent所对应的事务都需要调用 onHandleIntent 这个抽象方法。所以,将对不同任务的不同操作通过实现 onHandleIntent 方法就可完成。
执行完这个任务(Intent)就会自动停止 Service 。这里有一点需要注意,如果这个任务的执行本身就是异步的,所以,假如添加的任务也是异步的,很难保证能正常执行结束。
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);
}
}
|
从代码可以看出,每执行一次onHandleIntent 都会调用执行 stopSelf 来停止当前的service。也就是假如子类实现的 onHandleIntent 中执行的是异步任务,异步任务可能得不到预期的结果。
举个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
public static void startActionBaz(Context context, String param1, String param2) {
Intent intent = new Intent(context, MyIntentService.class);
intent.setAction(ACTION_BAZ);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() dead");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_BAZ.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM1);
final String param2 = intent.getStringExtra(EXTRA_PARAM2);
handleActionBaz(param1, param2);
}
}
}
private void handleActionBaz(String param1, String param2) {
Log.d(TAG, "handleActionBaz() called with: " + "param1 = [" + param1 + "], param2 = [" + param2 + "]");
new Thread(new Runnable() {
@Override
public void run() {
try {
//这里的代码是无法执行的。
Thread.sleep(3000);
Log.d(TAG, "handleActionBaz() called at Thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
|
以上代码中的 Runnable 中的代码是不会执行的。
看下启动两次 IntentService 的log输出。
1
2
3
4
5
6
|
07-02 10:04:03.799 4785-4785/cn.steve.study D/MyIntentService: MyIntentService() called with: cn.steve.service.MyIntentService@f26cde3
07-02 10:04:03.811 4785-5288/cn.steve.study D/MyIntentService: handleActionBaz() called with: param1 = [], param2 = []
07-02 10:04:03.840 4785-4785/cn.steve.study D/MyIntentService: onDestroy() dead
07-02 10:04:04.079 4785-4785/cn.steve.study D/MyIntentService: MyIntentService() called with: cn.steve.service.MyIntentService@47d6d5e
07-02 10:04:04.089 4785-5293/cn.steve.study D/MyIntentService: handleActionBaz() called with: param1 = [], param2 = []
07-02 10:04:04.114 4785-4785/cn.steve.study D/MyIntentService: onDestroy() dead
|
发现每次都是新建 IntentService 对象,执行完后就会销往。
总结
系统为我们提供这个 IntentService 能在完成任务后自动停止销往,不需要我们手动停止,但是这个特性只能对一些简单的同步任务而已,对于异步任务,还是需要我们手动去 stop 。