前面介绍的Service在官方文档介绍中说Service存在着如下两个问题:
1.A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
2.A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
1、Service不会专门启动一条单独的进程,Service与它所在的应用在同一个进程中。
2、Service不是专门一条新的线程,因此不能再Service中直接处理耗时任务。
如果开发者在Service中处理耗时任务,建议在Service中另外启动一条新的线程来处理耗时的任务,可能有的朋友就会问:“既然在Service中处理耗时任务需要启动新线程,为什么我们不直接在Activity中开启一个新线程,而要使用Service呢?”
其实这种在Activity中直接启动一个线程来实现对有些业务逻辑是非常不可靠的,比如:用户使用BroadcastReceiver来启动一个新线程,BroadcastReceiver的生命周期非常短,这样就可能存在这样的问题,在子线程还没有结束的情况下,BroadcastReceiver已经结束了,或者用户在Activity中启动一个新线程后直接退出,此时它们所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存时可能会优先终止该进程。如果宿主进程被终止,那么该进程内的所有子线程也会被终止,这样就有可能导致一些严重错误。
IntentService是Service的子类,所以它比Service增加了额外的功能,它正好弥补了Service的上述两点不足:IntentService将会使用队列来管理请求Intent,每当客户端代码通过Intent请求启动IntentService时,IntentService会将该Intent加入队列中,然后开启一条新的worker线程来处理该Intent.对于异步的startService()请求,IntentService会按次序依次处理队列中的Intent,该线程保证同一时刻只处理一个Intent.由于IntentService使用新的worker线程处理Intent请求,因此IntentService不会阻塞主线程,所以IntentService就可以处理耗时任务。
IntentService有如下特征:
1、会创建单独的worker线程来处理所有的Intent请求。
2、会创建单独的worker线程来处理onHandleIntent()方法实现的代码。
3、所有请求处理完成后,IntentService会自动停止,因此开发者无须调用stopSelf()方法
4、为Service的onBind()方法提供了默认的实现,默认实现的onBind()方法返回null
5、为Service的onStartCommand()方法提供了默认实现,该实现会将请求的Intent添加到队列中。
从上面的特点中可以看出来,扩展的IntentService实现Service无须重写onBind()方法和onStartCommand()方法,只要重写onHandleIntent()方法即可。
下面通过一个具体例子来说明IntentService和Service的区别:
(1)继承自Service的MyService类
package com.example.testservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service{ @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { //该方法内可以执行耗时任务,比如下载文件等 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; } }
读者可能会注意到onStartCommand方法最后的返回值我设置成了START_STICKY,有关返回值的详细设置及含义将在下一篇文章中介绍。
执行结果
可以看到在Service中执行耗时任务程序的主UI会被阻塞,出现ANR异常。
(2)继承自IntentService的MyIntentService类package com.example.testservice; import android.app.IntentService; import android.content.Intent; public class MyIntentService extends IntentService{ public MyIntentService(){ super("MyIntentService"); } @Override protected void onHandleIntent(Intent arg0) { //该方法内可以执行耗时任务,比如下载文件等 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("--耗时任务执行完毕--"); } }