
前言
-
多线程的应用在Android开发中是非常常见的,常用方法主要有:
- 继承Thread类
- 实现Runnable接口
- AsyncTask
- Handler
- HandlerThread
- IntentService
今天,我将主要介绍多线程
IntentService的工作原理 & 源码分析。
Carson带你学多线程系列
基础汇总
Android多线程:基础知识汇总
基础使用
Android多线程:继承Thread类使用(含实例教程)
Android多线程:实现Runnable接口使用(含实例教程)
复合使用
Android 多线程:AsyncTask使用教程(含实例讲解)
Android 多线程:AsyncTask原理及源码分析
Android多线程:HandlerThread使用教程(含实例讲解)
Android多线程:HandlerThread原理及源码分析
Android多线程:IntentService使用教程(含实例讲解)
Android多线程:IntentService的原理及源码分析
Android多线程:线程池ThreadPool全方位教学
相关使用
Android异步通信:这是一份全面&详细的Handler机制学习攻略
Android多线程:手把手教你全面学习神秘的Synchronized关键字
Android多线程:带你了解神秘的线程变量 ThreadLocal
目录

1. 定义
Android里的一个封装类,继承四大组件之一的Service
2. 作用
处理异步请求 & 实现多线程
3. 使用场景
线程任务 需 按顺序、在后台执行
- 最常见的场景:离线下载
- 不符合多个数据同时请求的场景:所有的任务都在同一个
Thread looper里执行
4. 工作原理
4.1 流程示意图
-
IntentService的工作原理 & 源码工作流程如下:

4.2 特别注意
若启动IntentService 多次,那么 每个耗时操作 则 以队列的方式 在 IntentService的 onHandleIntent回调方法中依次执行,执行完自动结束
接下来,我们将通过 源码分析 解决以下问题:
-
IntentService如何单独开启1个新的工作线程 -
IntentService如何通过onStartCommand()将Intent 传递给服务 & 依次插入到工作队列中
5. 源码分析
问题1:IntentService如何单独开启1个新的工作线程
主要分析内容 = IntentService源码中的 onCreate()方法
@Override
public void onCreate() {
super.onCreate();
// 1. 通过实例化andlerThread新建线程 & 启动;故 使用IntentService时,不需额外新建线程
// HandlerThread继承自Thread,内部封装了 Looper
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
// 2. 获得工作线程的 Looper & 维护自己的工作队列
mServiceLooper = thread.getLooper();
// 3. 新建mServiceHandler & 绑定上述获得Looper
// 新建的Handler 属于工作线程 ->>分析1
mServiceHandler = new ServiceHandler(mServiceLooper);
}
/**
* 分析1:ServiceHandler源码分析
**/
private final class ServiceHandler extends Handler {
// 构造函数
public ServiceHandler(Looper looper) {
super(looper);
}
// IntentService的handleMessage()把接收的消息交给onHandleIntent()处理
@Override
public void handleMessage(Message msg) {
// onHandleIntent 方法在工作线程中执行
// onHandleIntent() = 抽象方法,使用时需重写 ->>分析2
onHandleIntent((Intent)msg.obj);
// 执行完调用 stopSelf() 结束服务
stopSelf(msg.arg1);
}
}
/**
* 分析2: onHandleIntent()源码分析
* onHandleIntent() = 抽象方法,使用时需重写
**/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
问题2:IntentService 如何通过onStartCommand() 将Intent 传递给服务 & 依次插入到工作队列中
/**
* onStartCommand()源码分析
* onHandleIntent() = 抽象方法,使用时需重写
**/
public int onStartCommand(Intent intent, int flags, int startId) {
// 调用onStart()->>分析1
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
/**
* 分析1:onStart(intent, startId)
**/
public void onStart(Intent intent, int startId) {
// 1. 获得ServiceHandler消息的引用
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
// 2. 把 Intent参数 包装到 message 的 obj 发送消息中,
//这里的Intent = 启动服务时startService(Intent) 里传入的 Intent
msg.obj = intent;
// 3. 发送消息,即 添加到消息队列里
mServiceHandler.sendMessage(msg);
}
至此,关于IntentService的源码分析讲解完毕。
6. 源码总结
从上面源码可看出:IntentService本质 = Handler + HandlerThread:
- 通过
HandlerThread单独开启1个工作线程:IntentService - 创建1个内部
Handler:ServiceHandler - 绑定
ServiceHandler与IntentService - 通过
onStartCommand()传递服务intent到ServiceHandler、依次插入Intent到工作队列中 & 逐个发送给onHandleIntent() - 通过
onHandleIntent()依次处理所有Intent对象所对应的任务
因此我们通过复写
onHandleIntent()& 在里面 根据Intent的不同进行不同线程操作 即可
7. 注意事项
此处,有两个注意事项需要关注的:
- 工作任务队列 = 顺序执行
- 不建议通过 bindService() 启动 IntentService
注意事项1:工作任务队列 = 顺序执行
即 若一个任务正在
IntentService中执行,此时你再发送1个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕后才开始执行
- 原因:
- 由于
onCreate()只会调用一次 = 只会创建1个工作线程; - 当多次调用
startService(Intent)时(即onStartCommand()也会调用多次),其实不会创建新的工作线程,只是把消息加入消息队列中 & 等待执行。 - 所以,多次启动 IntentService 会按顺序执行事件
若服务停止,则会清除消息队列中的消息,后续的事件不执行
注意事项2:不建议通过 bindService() 启动 IntentService
原因:
// 在IntentService中,onBind()`默认返回null
@Override
public IBinder onBind(Intent intent) {
return null;
}
- 采用
bindService()启动IntentService的生命周期如下:
onCreate() ->> onBind() ->> onunbind()->> onDestory()
- 即,并不会调用
onStart()或onStartcommand(),故不会将消息发送到消息队列,那么onHandleIntent()将不会回调,即无法实现多线程的操作
此时,你应该使用
Service,而不是IntentService
8. 对比
此处主要讲解IntentService与四大组件Service、普通线程的区别。
8.1 与Service的区别

8.2 与其他线程的区别

9. 总结
- 本文主要 全面介绍了 多线程
IntentService的工作原理 & 源码分析 - 下一篇文章我将对讲解
Android多线程的相关知识,感兴趣的同学可以继续关注Carson_Ho的简书
Carson带你学多线程系列
基础汇总
Android多线程:基础知识汇总
基础使用
Android多线程:继承Thread类使用(含实例教程)
Android多线程:实现Runnable接口使用(含实例教程)
复合使用
Android 多线程:AsyncTask使用教程(含实例讲解)
Android 多线程:AsyncTask原理及源码分析
Android多线程:HandlerThread使用教程(含实例讲解)
Android多线程:HandlerThread原理及源码分析
Android多线程:IntentService使用教程(含实例讲解)
Android多线程:IntentService的原理及源码分析
Android多线程:线程池ThreadPool全方位教学
相关使用
Android异步通信:这是一份全面&详细的Handler机制学习攻略
Android多线程:手把手教你全面学习神秘的Synchronized关键字
Android多线程:带你了解神秘的线程变量 ThreadLocal
欢迎关注Carson_Ho的简书
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。
