概述
Service是在主线程中,因此不应该在Service中直接处理耗时的任务,一般我们要在Service中开启一个子线程去执行耗时操作。
IntentService是Service的子类,比普通的Service多了一个额外的功能,就是会创建独立的worker线程来处理所有的Intent请求。
源码分析
首先来看onCreate():
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);
}
这里创建了一个HandlerThread,HandlerThread就是一个自带Looper的线程,具体可以参考HandlerThread源码分析。
然后为这个HandlerThread创建了一个处理消息的ServiceHandler,ServiceHandler是Hanlder的子类:
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()关闭自己。
来看onHandleIntent():
/**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
* This may be null if the service is being restarted after
* its process has gone away; see
* {@link android.app.Service#onStartCommand}
* for details.
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
以上注释的意思是当某个请求需要处理时,这个方法会在工作线程被调用,一次仅仅会有一个请求被处理,但是处理过程会运行在工作者线程(独立于其他应用程序逻辑运行)。因此,如果某段代码需要执行很长时间,它会阻塞住其他提交到该IntentService的请求,但是不会阻塞住其他任何东西。当所有的请求被处理完成之后,IntentService会停止它自身,因此你不应该手动调用stopSelf()方法。
如果有多个任务的时候,stopSelf(int startId)中会去判断这个startId是否是最新的,如果是最新的就停止Service,如果不是,肯定是因为又新加入了任务,这个时候就不停止。
- 补充:stopSelf()其实就是stopSelf(-1),这就直接停止了。
我们还能看到在IntentService的onDestroy()中退出了工作线程:
@Override
public void onDestroy() {
mServiceLooper.quit();
}
那消息是怎么传递给IntentService的呢,我们看到onStart():
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
当startService()之后,onStart()会被调用,这个可以参考【Android】Service的生命周期。
我们看到onStart()中利用mServiceHandler以消息的形式向创建的子线程发送了传递进来的Intent。
到这里一切都明白了。
下面来看一个demo,
TestIntentServiceActivity:
public class TestIntentServiceActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_intent_service);
for (int i = 0; i < 5; i++) {
startService(new Intent(TestIntentServiceActivity.this, MyIntentService.class));
}
}
}
MyIntentService:
public class MyIntentService extends IntentService {
public static final String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
for (int i = 0; i < 5; i++) {
SystemClock.sleep(50);
Log.d(TAG, Thread.currentThread().getName() + " " + i);
}
Log.d(TAG, Thread.currentThread().getName() + " " );
}
}
运行起来之后,Log的结果是这样的:
08-31 12:49:58.416 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 0
08-31 12:49:58.467 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 1
08-31 12:49:58.519 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 2
08-31 12:49:58.570 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 3
08-31 12:49:58.621 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 4
08-31 12:49:58.621 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService]
08-31 12:49:58.704 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 0
08-31 12:49:58.755 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 1
08-31 12:49:58.806 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 2
08-31 12:49:58.857 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 3
08-31 12:49:58.909 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 4
08-31 12:49:58.909 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService]
08-31 12:49:58.962 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 0
08-31 12:49:59.013 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 1
08-31 12:49:59.064 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 2
08-31 12:49:59.116 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 3
08-31 12:49:59.169 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 4
08-31 12:49:59.169 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService]
08-31 12:49:59.221 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 0
08-31 12:49:59.272 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 1
08-31 12:49:59.322 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 2
08-31 12:49:59.375 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 3
08-31 12:49:59.426 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 4
08-31 12:49:59.426 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService]
08-31 12:49:59.479 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 0
08-31 12:49:59.531 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 1
08-31 12:49:59.582 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 2
08-31 12:49:59.632 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 3
08-31 12:49:59.685 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService] 4
08-31 12:49:59.685 2839-2894/com.example.tsnt D/MyIntentService: IntentService[MyIntentService]
完全符合我们以上的分析。
最后有一点注意,IntentService 源码中的 onBind() 默认返回 null;不适合 bindService() 启动服务,如果你执意要 bindService() 来启动 IntentService,可能因为你想通过 Binder 或 Messenger 使得 IntentService 和 Activity 可以通信,这样那么 onHandleIntent() 不会被回调,相当于在你使用 Service 而不是 IntentService。
参考:
1.IntentService 示例与详解
2.Android理解:IntentService
3.Android:IntentService的使用
4.IntentService使用