概述
Android中的Service是运行在主线程(UI线程),如果要处理耗时任务,需要手动创建工作线程,不然会有ANR的风险。IntentService继承于Service,内部使用工作线程来处理请求的任务。
使用
Step1. 定义IntentService的子类:传入线程名称、重写onHandleIntent()
方法
1 2 3 4 5 6 7 8 9 10 11 12
| public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { } }
|
Step2. 在AndroidManifest.xml注册
1 2 3
| <service android:name=".MyIntentService" android:exported="false"/>
|
Step3. 发送任务请求
1 2
| Intent intent = new Intent(context, MyIntentService.class); context.startService(intent);
|
源码分析
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 65 66 67 68 69 70 71
| public abstract class IntentService extends Service { private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery;
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); } }
public IntentService(String name) { super(); mName = name; }
public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; }
@Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
@Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
@Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }
@Override public void onDestroy() { mServiceLooper.quit(); }
@Override @Nullable public IBinder onBind(Intent intent) { return null; }
@WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent); }
|
stopSelf()和stopSelf(int startId)的区别:
在调用stopSelf(startId)时,系统会检测是否还有startId存在,如果存在,则不销毁Service,否则销毁Service。即stopSelf(startId)和onStartCommand()成对的时候,Service才被销毁。
在调用stopSelf()时,实际调用的是stopSelf(-1),那么将直接销毁Service,系统就不会检测是否还有其他的startId存在。
总结:
从上面源码可以看出,IntentService本质是采用Handler和HandlerThread方式:
- 通过
HandlerThread
单独开启一个线程;
- 创建一个名为
ServiceHandler
的内部Handler;
- 将
ServiceHandler
与HandlerThread
所对应的子线程进行绑定;
- 通过
onStartCommand()
传递给服务的Intent,依次插入到工作队列中,并逐个发送给onHandleIntent()
;
- 通过
onHandleIntent()
来依次处理所有Intent请求对象所对应的任务。
使用场景
- 线程任务需要按顺序,在后台执行的使用场景,如:离线下载。
- 由于所有的任务都在一个Thread Looper里面来做,所以不适合多个数据同时请求的场景。
对比
IntentService与Service的区别
- Service依赖于应用程序的主线程,所以不宜在Service中编写耗时的逻辑和操作,否则会引起ANR;IntentService创建一个工作线程来处理任务。
- Service需要主动调用
stopSelf()
来结束服务,而IntentService不需要(在所有Intent处理完后,系统会自动关闭服务)。
IntentService与其他线程的区别
- IntentService内部采用HandlerThread实现,作用类似于后台线程。
- 与后台线程相比,IntentService是一种后台服务,优势是:优先级高,不易被系统杀死,从而保证任务的执行。(对于后台线程,若进程中没有活动的四大组件,则该线程的优先级非常低,容易被系统杀死,无法保证任务的执行。)
参考链接
- IntentService详解
- IntentService
- Create a background service
- Service
- Android Service stopSelf