前言
-
多线程的应用在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的简书
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。