前言

源码分析篇,分析过程也参考过各位大神的成果。知识在于分享,学会了就是自己的,有参考过的,也会尽量给出链接(看了很多,可能无法一一给出);希望共同进步,站在巨人肩膀上看世界!

参考:http://blog.csdn.net/smbroe/article/details/45009721

以下用法和源码分析基于android-27(即版本android 8.1.0)

要点总结

1.生命周期onCreate --> onStartCommand --> onStart --> onHandleIntent --> onDestroy其中onCreate、onStartCommand、onStart、onDestroy运行在ui线程,onHandleIntent运行在子线程;2.如果每次onHandleIntent执行的时间足够长的话,连续循环启动IntentService的onCreate只会执行一次,而onStartCommand、onStart则启动几次就执行几次,onHandleIntent也是启动几次就执行几次,onDestroy只执行一次;对应onHandleIntent来说是串行的,对同一进程内同一IntentService来说必须按序排队依次执行;即如果IntentService未执行完任务时,不会再次启动新的IntentService,而是会使用原IntentService排队执行任务,全部任务执行完毕后,才退出IntentServie;3.如果启动IntentService时,前边的任务已经执行结束并退出后,则会再次创建onCreate并执行4.需要提供无参的构造函数,然后调用父类的有参构造;Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的5.假设在onHandleIntent中创建handler并执行操作:@Overrideprotected void onHandleIntent(@Nullable Intent intent) {Log.d(TAG,"onHandleIntent"+" ,"+Thread.currentThread());Handler temphandler=new Handler(){@Overridepublic void handleMessage(Message msg) {Log.d(TAG,"handleMessage"+" ,"+Thread.currentThread());}};temphandler.sendEmptyMessageDelayed(1,5000);}这样handleMessage是不会执行的,因为此时temphandler获取的是intentService中HandlerThread的looper,而在onHandleIntent执行完后,会调用onDestroy退出整个消息队列,所以这边的handleMessage就执行不到了;如果temphandler是在外部初始化的就可以,默认会拿的mainlooper;
复制代码

优缺点

优点:

  • 1.与service都运行于ui线程不同,intentService在子线程中处理耗时任务,避免堵塞造成anr;

  • 2.自己维护消息队列,实现排队执行,避免多线程资源同步问题;

  • 3.无需手动停止intentservice,任务都执行完毕后自动销毁;

  • 4.存在已启动的正在使用的intentServie的话,再次启动不会重复创建,而是共用一个节省不必要资源开销

缺点:

  • 1.处理完成之后要通知ui的话,相对麻烦,可能需要使用ui线程的handler或者广播。

使用方法

//创建实现IntentService的子类并在AndroidMainfest.xml中声明
<service android:name=".MyIntentService"></service>public class MyIntentService extends IntentService{String TAG="MyIntentService";public MyIntentService() {   //需要提供默认的无参构造函数,然后调用父类的有参构造this("MyIntentService");}public MyIntentService(String name) {super(name);}@Overridepublic void setIntentRedelivery(boolean enabled) {super.setIntentRedelivery(enabled);Log.d(TAG,"setIntentRedelivery:"+enabled+" ,"+Thread.currentThread());}@Overridepublic void onCreate() {super.onCreate();Log.d(TAG,"onCreate"+" ,"+Thread.currentThread());}@Overridepublic void onStart(@Nullable Intent intent, int startId) {super.onStart(intent, startId);Log.d(TAG,"onStart"+" ,"+Thread.currentThread());}//这边的intent可以获取startService中传递进来的参数@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {Log.d(TAG,"onStartCommand:"+startId+" ,"+Thread.currentThread());return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG,"onDestroy"+" ,"+Thread.currentThread());}@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG,"onBind"+" ,"+Thread.currentThread());return super.onBind(intent);}//这边的intent可以获取startService中传递进来的参数@Overrideprotected void onHandleIntent(@Nullable Intent intent) {Log.d(TAG,"onHandleIntent"+" ,"+Thread.currentThread());}
}//启动intentServiceIntent intent = new Intent(SecondActivity.this,MyIntentService.class);intent.putExtra("parmas1","abcd");//..按需要携带参数intent.putExtra("parmas2",true);SecondActivity.this.startService(intent);
复制代码

源码分析

onCreate函数

private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;@Overridepublic 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);}
复制代码
在OnCreate中创建了一个HandlerThread,并获取其中的looper创建ServiceHandler(继承自Handler),使得ServiceHandler可以在子线程中处理消息
复制代码

onStartCommand函数

/*** You should not override this method for your IntentService. Instead,* override {@link #onHandleIntent}, which the system calls when the IntentService* receives a start request.* @see android.app.Service#onStartCommand*/@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}
复制代码
对于onStartCommand只是简单的调用了onStart方法
复制代码

onStart函数

@Overridepublic void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}
复制代码
在onStart方法中,所做的处理便是将startService传递过来的Intent和启动startId包装在Message中传递给ServiceHandler进行处理
复制代码

回调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);}}
复制代码
而在ServiceHandler中,便是回调执行用户重写的onHandleIntent方法,
执行完毕之后,注意调用的stopSelf(startId),Handler中我们处理完每一个命令都会调用stopSelf(int)方法来停止服务:该方法需要来自onStartCommand方法中的启动ID,只有传入的startId是onStartCommand方法中接收到的最新启动ID时才会停止服务,就是说,我们的IntentService直到命令队列中的所有命令被执行完后才会停止服务。//会停止service并回调onDestroy
public final void stopSelf() {stopSelf(-1);
}//会判断传入的startId与当前startService所传入的startId是否一致,一致才停止Service并回调onDestroy,否则不停止,由此实现连续多次启动IntentService时,每次回调执行完onHandleIntent后,不会立即退出IntentService,而是接着执行Handler队列中的消息
public final void stopSelf(int startId) {if (mActivityManager == null) {return;}try {mActivityManager.stopServiceToken(new ComponentName(this, mClassName), mToken, startId);} catch (RemoteException ex) {}
}
复制代码

onDestroy函数

@Overridepublic void onDestroy() {mServiceLooper.quit();}
复制代码
退出消息队列

Android源码之路(一、IntentService)相关推荐

  1. Android源码之路(二、AsyncTask)

    参考 https://www.baidu.com/link?url=QNRznJEBT25k0bpgVD3bOniOia2W85eiPIWrS93YFknyrHoFDGrJVtoax2ZYpiiErt ...

  2. 读万卷书不如行万里路,行万里路不如阅人无数,阅人无数不如名师指路,名师指路不如自己去悟,自己去悟不如分析android源码深处...

    首先,作为一个已经学习android 一年多的人来说,如何选择android书籍,如何学习android 的app的开发,心中或多或少都有一些眉目,看了这本书的试读章节,真心感觉挺不错的.值得推荐,自 ...

  3. androidstudio调试android 源码 jni,在android studio下配置gradle用ndk-build和ndk-gbd编译调试JNI...

    因为要在旧版android在做一些工作.所以做用到了它.目标平台是:android api 10和armv6. 开发环境是:AS 版本2.3.2; SDK版配android 2.3.3(api10); ...

  4. 大牛教你这样阅读android源码

    当你去面试时,经常会被问到,你是否阅读过android系统源码?那系统源码该如何阅读呢? 下面,让我们来看看大牛们是如何阅读的(来自知乎的牛人们http://www.zhihu.com/questio ...

  5. 速通AOSP,成功编译调试Android源码

    /   今日科技快讯   / 近日据不少网友反馈,爱奇艺App开始对投屏功能作出限制,之前黄金VIP会员支持最高4K清晰度投屏,现在只能选最低的480P清晰度,要想进行4K投屏必须购买白金VIP会员. ...

  6. Android源码分析工具及方法

    转载自:http://bbs.pediy.com/showthread.php?t=183278 标 题: [原创]Android源码分析工具及方法 作 者: MindMac 时 间: 2014-01 ...

  7. Android 源码分析工具

    2019独角兽企业重金招聘Python工程师标准>>> 标 题: [原创]Android源码分析工具及方法 作 者: MindMac 时 间: 2014-01-02,09:32:35 ...

  8. Android源码编译详解【四】:Android 6.0_源码的下载与编译

     1.AOSP源码下载  AOSP:即为"Android Open-Source Project"的缩写,中文意为 :"安卓开放源代码项目". Google官方 ...

  9. Android 源码编译详解【合集篇】

    Android 源码编译详解[一]:服务器硬件配置及机型推荐 做 Android系统开发多年,开发环境都是入职就搭建好了,入职时拿个账号密码就直接开始搞开发了,年初换了新公司,所有的项目都是刚起步,一 ...

最新文章

  1. Python开发基础总结之函数+闭包+字典+列表
  2. SeciLog 1.3.1 发布,增加了全屏配置,自定义预警等新功能
  3. 《Groovy极简教程》第12章 Groovy的JSON包
  4. Git 经常使用命令总结
  5. 多个相同参数表单提交
  6. python 两阶段聚类_Python,如何对多元时间序列进行聚类?
  7. css 超出N行文本如何处理
  8. python视频处理代码_Python装逼指南——五行代码实现批量抠图,附视频抠图
  9. NDVI归一化差异植被指数
  10. 全自动高清录播服务器,高清高清录播服务器 高清全自动录播系统 方便携带 搭建快捷...
  11. oppoa5降级教程_OPPO A5官方出厂rom系统刷机包下载_卡刷升级包降级回退包
  12. java Base64带秘钥的加密解密
  13. 机器学习—确定系数R2
  14. 无法直接打开jar文件,提示“你要以何种方式打开.jar文件”(已解决)
  15. pandas parquet文件读取pyarrow、feather文件保存与读取;requests 或wget下载图片文件
  16. 入门级短信推送,你还不会吗?
  17. 计蒜客:Cryptographer's Conundrum
  18. 主题模型简介(topic model)
  19. VoLTE KPI指标分类和定义
  20. 2016年工作总结以及2017年工作计划

热门文章

  1. 华为鸿蒙系统发展时间2021年,耗时八年打造国产系统,华为鸿蒙OS质疑声不断,它才是真正未来...
  2. java mongocollection_MongoDb完结笔记-与java结合
  3. linux video属性_Linux 下Video 的制作方法
  4. 面试官问你Java内存区域你用new创建对象来解释
  5. C++特殊符号:【优先级】
  6. 【转】认识 C++ 中的 explicit 关键字
  7. WMI 获得已安装应用程序列表
  8. 08_提升方法Boosting1_统计学习方法
  9. redhat7 常用命令
  10. ios 判断某个时间是周几的方法