活儿好又不纠缠的 IntentService

版权声明:android

本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。多线程

未经容许,不得转载。oop

1、前言

Service 是 Android 四大组件之一,正常来讲,咱们直接使用 Service 就能够了。ui

可是 Service 存在几个问题:this

  1. 默认不会运行在单独的进程中,而是和所在应用共用同一个进程。
  2. Service 也是在主线程中运行,因此一些耗时操做,依然须要单独开启线程去执行。

第一个问题其实并非什么大的问题,可是正常来讲,咱们使用 Service 就是想在后台执行一些其余的操做,例如:下载等,而这些,又须要额外开启线程来完成任务,这样无形之中加大了咱们的代码量。线程

而 IntentService 就是为这个而生的。设计

2、什么是IntentService

IntentService 是继承自 Service 的,因此它本质上仍是一个 Service 。在 IntentService 内部维护了一个 WorkerThread 来专门处理耗时操做,实际上它会将全部 IntentService 的业务操做都放在 WorkerThread 中执行。3d

若是 start 了屡次相同的 IntentService ,那么每一次 start 的任务,都会在 WorkerThread 中依次执行。而最让咱们省心的是,IntentService 在执行完这些任务以后,会调用 stopSelf() 结束本身。code

从官方文档能够了解到,一些 IntentService 的特色:cdn

  1. 它会建立独立的 WorkerThread 来处理全部的 Intent 请求。
  2. 它会建立独立的 WorkerThread 来处理 onHandleIntent() 的实现代码,无需担忧多线程的问题。
  3. 全部请求完成以后,IntentService 会自动中止。
  4. 它的 onBind() 默认返回 null,不要去实现它,不要用 bindService() 绑定一个 IntentService。
  5. 它的 onStartCommand() 提供了默认的实现,会将请求的 Intent 添加到队列中。

从上面的介绍能够了解到,在 IntentService 开启了一个独立的 WorkerThread 来完成具体任务的执行,而咱们只须要将须要完成的业务代码,在 onHandleIntent() 中实现便可。

3、如何使用 IntentService

既然已经对 IntentService 有一个简单的认识了,那么接下来就实现一个最简单的 IntentService 的 Demo。

IntentService 自己已经帮咱们实现了大部分逻辑,咱们只须要在 onHandleIntent() 中实现咱们的业务逻辑代码便可。

Demo 中给的例子,其实什么也没作,就是 Thread.sleep() 了一会,而后输出了一些 Log。这样就完成了一个最简单的 IntentService 。

IntentService 使用起来也很是的简单,只须要经过构造方法传递 String 类型的参数,用于指定 WorkerThread 的名字,而后和日常使用 Service 同样调用 startService() 便可。
startService(new Intent(MainActivity.this,MyIntentService.class));

IntentService 依然仍是一个 Service,因此须要在 AndroidManifest.xml 中为它注册。

<service android:name=".MyIntentService"/>

这里快速对 MyIntentService 调用三次 startService(),咱们来看看输出的结果。

能够看到,每次 startService 的 startId 都不相同,而 IntentService 每次执行完成当前任务以后,会根据 startId 调用 stopSelf() 方法来标记须要中止服务,当最终没有须要执行的任务的时候,才会 onDestory() 销毁本身。这个细节,下一小结会详细讲解。

3、IntentService 如何实现它的特性

既然已经了解了 IntentService 的特性和如何使用它,接下来不看看具体它是如何实现的,总感受缺乏点什么。

那么咱们就来从源码的角度,看看它是如何实现的。自己整个类,也只有不到二百行代码,真实有效的代码也就那么十几行,很是好理解。

先来看看 IntentService 是如何为一个 WorkerThread 的。

能够看到它其实是使用了一个 HandlerThread 来维护线程的,而在 HandleThread 中,内部已经维护一个 Looper,这里直接使用 HandlerThread 的 Looper 对象,便于在 IntentService 中去维护消息队列,而这里最终建立的 mServiceHandler 是属于 HandleThread 这个 WorkerThread 的。

而在 ServiceHandler 中,直接转发 Message 中携带的 Intent 对象,给 onHandleIntent() 方法去执行具体的业务逻辑。执行完成以后,当即调用 stopSelf() 方法中止本身,注意这里 stopSelf() 方法的参数是 arg1。

接下来看看当咱们调用 startService() 的时候,IntentService 到底干了什么?

onStartCommand() 中直接调用了 onStart() 方法,而上面 stopSelf() 方法使用的 arg1 正是这个 Service 的 startId,也就是说,它是会指定 startId 来中止当前的这次任务服务。而 Service 若是被启动屡次,就会存在多个 startId ,当全部的 startId 都被中止以后,才会调用 onDestory() 自我销毁。这也解释了为何屡次 start 同一个 IntentService 它会顺序执行,所有执行完成以后,再自我销毁。

最终会在 onDestory() 中调用 quit 去退出 Looper 的循环,释放资源。

4、查缺补漏

自己 IntentService 适用的场景,就是一种无状态的 Service,因此它是不支持 bindService() 方法去 bound 一个服务的。正如它的 onBind() 实现,直接返回一个 null。

固然若是你强制想要使用 bindService() 去实现 onBind() 方法,也是能够的,比较 IntentService 自己也是一个 Service,可是这样就不符合 IntentService 的设计规范,破坏了它使用完成以后自我销毁的理念,这个时候仍是推荐使用正常的 Service 便可。

而若是确实有完成以后交互的需求,能够考虑使用 EventBus 或者 LocalBroadcastManager 这种通讯的方式来传递数据,都是一种不错的方案。

公众号二维码.jpg
相关文章
相关标签/搜索