在Android
的四大组件中,Service
排行老二,在Android
中的主要作用是后台服务,进行与界面无关的操作。由于Service
运行在主线程,所以进行异步操作需要在子线进行。为此Android
为我们提供了IntentService
。 IntentService
是一个抽象类,继承至Service
,主要方便我们新建工作线程进行异步操作。提交任务到IntentService
时,异步任务以串行方式进行处理,意味着工作线程一次只处理一个任务。而且当所有任务都完成之后,会自动停止Service
,不需要我们手动停止。
IntentService 的使用
- 我们定义
DownloadService
类并继承至IntentService
。来模拟网络下载的过程。
public class DownloadService extends IntentService {private static int count = 0;/*** 主要用于调用服务类构造器** @param name 用于区分不同任务*/public DownloadService(String name) {super(name);}/*** AndroidManifest.xml配置清单需要配置** @param*/public DownloadService() {super("action");}/***主要重写该方法,在该方法内进行异步操作。**/@Overrideprotected void onHandleIntent(Intent intent) {Log.i("Download", "onHandleIntent" + count);count++;String name = intent.getStringExtra("action");if (name.equals("download")) {for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();return;}Log.i("Download", "download:" + count);}}}//以下方法的重写,仅仅为了打印日志@Overridepublic void onDestroy() {super.onDestroy();Log.i("Download", "onDestroy");}@Overridepublic void onCreate() {super.onCreate();Log.i("Download", "onCreate");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);Log.i("Download", "onStart");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("Download", "onStartCommand");return super.onStartCommand(intent, flags, startId);}
}复制代码
- 在AndroidManifest.xml配置
DownloadService
。
<service android:name=".DownloadService"/>
复制代码
- 在MainActivity类中循环调用Service,启动多循环任务。
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent=new Intent(this,DownloadService.class);for (int i =0;i<3;i++){intent.putExtra("action","download");intent.putExtra("count",""+i);startService(intent);}}
复制代码
- 运行结果
分析: 从运行结果知道,IntentService
在运行多个任务情况下,只调用一次onCreate
,调用多次onStartCommand
,跟Service
的生命周期一致。但,只有在运行完download:1
之后才会去运行download:2
,接着是download:3
。最后所有任务结束后会自动调用onDestroy
,停止服务。在这里需要注意的是,和Service
并不同,Service
需要我们手动停止服务。对于结果的回调,可以采用接口回调,广播,EventBus
。
那么,IntentService
是如何在Service
中实现异步操作和串行处理任务的呢?
IntentService内部实现
- 查看IntentService的onCreate方法
@Overridepublic void onCreate() {super.onCreate();//分析一HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();分析二mServiceHandler = new ServiceHandler(mServiceLooper);}
复制代码
分析一
HandThread
继承Thread
,通过start
方法创建工作线程,内部建立Looper
来达到消息循环,通过Hanlder
消息机制来达到串行的效果和处理多任务。HandThread
和Handler
消息机制,可以另外查看文章。
分析二
ServiceHandler
继承Handler
,与普通的Handler
并没有区别,在其内容处理handleMessage
。即调用IntentService
的onHandleIntent
;
private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}
复制代码
- 那么,当我们在
Activity
中重复调用startService
方法时,只会多次调用onStartCommand
方法,并不会重复调用onCreate
方法。我们看看onStartComamnd
方法的实现。
@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}
复制代码
可以看得出,调用了onStart
方法了。而onStart方法只是将我们的Intent包装成Message,通过Handler发送出去,并在Handler中进行处理,调用我们的onHandleIntent
。进而调用我们实现onHandleIntent
的代码。
@Overridepublic void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}
复制代码
总结
IntentService
并没有什么的新的技术含量,在了解HandlerTread和Handler的消息机制下,对Handler+Thread+Service
作一个封装,更适合我们后台进行异步耗时操作的场景。有效避免通过new
多个Thread
。
知识点分享
Android消息机制
HandlerThread必知必会