Android中IntentService的使用
一、简介
IntentService 是 Service 的子类,因此它不是普通的 Service。
1.Service 本身存在两个问题:
- Service 不会专门启动一个单独的进程,也就是说 Service 与它所在的应用位于同一个进程中。
- Service 不是一条新的线程,因此不应该在 Service 中直接处理耗时的任务。
基于以上两个问题,如果开发者需要在 Service 中处理耗时的任务,建议在 Service 中另外启动一条新的线程来处理耗时任务。当然你也可以使用上面说到的 IntentService,IntentService则弥补了这两个问题。
2.IntentService 的基本原理
IntentService 将会使用队列来管理请求 Intent, 每当客户端代码通过 Intent 请求启动 IntentService 时,IntentService 会将 Intent 加入队列中,然后开启一条新的 worker 线程来处理该 Intent 。对于异步的 startService() 请求,IntentService 会按次序处理队列中的 Intent,该线程保证同一时刻只处理一个 Intent。由于 IntentService 使用新的 worker 线程处理 Intent 请求,因此 IntentService 不会阻塞主线程,其自身就可以处理耗时任务。
IntentService 特征归纳如下:
- IntentService 会创建单独的 worker 线程来处理所有的 Intent 请求。
- IntentService 会创建单独的 worker 线程来处理 onHandleIntent()方法实现的代码,因此开发者无需处理多线程问题。
- 当所有请求处理完成后,IntentService 会自动停止,因此开发者无须调用 stopSelf() 方法来停止该 Service 。
- 为 Service 的 onBind() 方法提供了默认的实现,默认实现的 onBind() 方法返回 null。
- 为 Service 的 onStartCommand() 方法提供了默认的实现,该实现会将请求 Intent 添加到队列中
总起来说,IntentService 无须重写 onBind(),onStartCommand() 方法,只需要重写 onHandleIntent() 方法即可。
二、使用(实例)
一个简单的例子,两个按钮分别用于启动 Service 和 IntentService。两个 Service 都需要处理耗时任务。代码如下:
1.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
android:text="@string/start_service" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startIntentService"
android:text="@string/start_intent_service" />
</LinearLayout>
2.MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View source) {
// 创建需要启动的Service的Intent
Intent intent = new Intent(this, MyService.class);
// 启动Service
startService(intent);
}
public void startIntentService(View source) {
// 创建需要启动的IntentService的Intent
Intent intent = new Intent(this, MyIntentService.class);
// 启动IntentService
startService(intent);
}
}
3.MyService
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 该方法内执行耗时任务可能导致ANR(Application Not Responding)异常
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("---耗时任务执行完成---");
return START_STICKY;
}
}
4.MyIntentService
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// 该方法内可以执行任何耗时任务,比如下载文件等,此处只是让线程暂停20秒
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStartCommand");
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("---耗时任务执行完成---");
}
}
运行程序你会发现,普通 Service 由于阻塞主线程而出现 ANR(Application Not Responding)异常,但 IntentService 会使用单独的线程来处理耗时的任务,所以不会阻塞主线程。