为什么我们需要IntentService ?
Android中的IntentService是继承自Service类的,在我们讨论IntentService之前,我们先想一下Service的特点: Service的回调方法(onCreate、onStartCommand、onBind、onDestroy)都是运行在主线程中的。当我们通过startService启动Service之后,我们就需要在Service的onStartCommand方法中写代码完成工作,但是onStartCommand是运行在主线程中的,如果我们需要在此处完成一些网络请求或IO等耗时操作,这样就会阻塞主线程UI无响应,从而出现ANR现象。为了解决这种问题,最好的办法就是在onStartCommand中创建一个新的线程,并把耗时代码放到这个新线程中执行。可以参考之前的文章《Android通过startService实现文件批量下载》,这篇文章在onStartCommand中开启了新的线程作为工作线程去执行网络请求,所以这样不会阻塞主线程。由此看来,创建一个带有工作线程的Service是一种很常见的需求(因为工作线程不会阻塞主线程),所以Android为了简化开发带有工作线程的Service,Android额外开发了一个类——–IntentService。
IntentService的特点
IntentService具有以下特点:
- 1. IntentService自带一个工作线程,当我们的Service需要做一些可能会阻塞主线程的工作的时候可以考虑使用IntentService。
- 2. 我们需要将要做的实际工作放入到IntentService的onHandleIntent回到方法中,当我们通过startService(intent)启动了IntentService之后,最终Android Framework会回调其onHandleIntent方法,并将intent传入该方法,这样我们就可以根据intent去做实际工作,并且onHandleIntent运行在IntentService所持有的工作线程中,而非主线程。
- 3. 当我们通过startService多次启动了IntentService,这会产生多个job,由于IntentService只持有一个工作线程,所以每次onHandleIntent只能处理一个job。面多多个job,IntentService会如何处理?处理方式是one-by-one,也就是一个一个按照先后顺序处理,先将intent1传入onHandleIntent,让其完成job1,然后将intent2传入onHandleIntent,让其完成job2…这样直至所有job完成,所以我们IntentService不能并行的执行多个job,只能一个一个的按照先后顺序完成,当所有job完成的时候IntentService就销毁了,会执行onDestroy回调方法。
如何使用IntentService ?
在《Android通过startService实现文件批量下载》一文中,我们演示了如何通过Service批量下载文章,现在在本文中我们还是要演示如何批量下载文章,只不过是用IntentService完成这项工作。
系统界面如下:
界面很简单,就一个按钮“批量下载文章”,通过该Activity上的按钮启动DownloadService。
代码如下:
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package
com.ispring.startservicedemo;
import
android.app.IntentService;
import
android.content.Intent;
import
android.util.Log;
import
java.io.IOException;
import
java.io.InputStream;
import
java.net.HttpURLConnection;
import
java.net.MalformedURLException;
import
java.net.URL;
public
class
DownloadIntentService
extends
IntentService {
public
DownloadIntentService(){
super
(
"Download"
);
Log.i(
"DemoLog"
,
"DownloadIntentService构造函数, Thread: "
+ Thread.currentThread().getName());
}
@Override
public
void
onCreate() {
super
.onCreate();
Log.i(
"DemoLog"
,
"DownloadIntentService -> onCreate, Thread: "
+ Thread.currentThread().getName());
|