异步处理老司机:IntentService 源码分析
IntentService 介绍
IntentService 是一种特殊的 Service,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能够使用 IntentService。它可用于执行后台耗时任务,当任务执行完成后它会自动停止,在资源不足时,系统会对一些被认为时无用的资源给清理掉,由于它是 Service 的原因,它的优先级比单纯的线程的优先级高很多,不容易被系统杀死(清理掉),所以它适合执行一些高优先级的后台任务。在实现上,IntentService 封装了 Handlerhread 和 Handler。
HandlerThread 继承了 Thread,它是一种可以使用 Handler 的 Thread。它的实现是通过在run()方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()方法来开启消息循环, 它的内部对Thread 的 run 方法进行重写,通过Handler的消息方式(Looper循环)来通知HandlerThread执行一个具体的任务。
@Override
public void run() {mTid = Process.myTid();Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid = -1;
}
在明确了不需要使用HandlerThread的时,可以通过它的quit或者quitSafely方法来终止线程的执行
public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false;
}public boolean quitSafely() {Looper looper = getLooper();if (looper != null) {looper.quitSafely();return true;}return false;
}
这两个方法的区别是:
quit()
使用此方法可能是不安全的,因为在Looper队列终止之前可能无法传递某些消息。
quitSafely()
使用此方法可能是安全的,因为一旦已经传递消息,队列中的所有剩余消息被处理,方法就会终止。然而,在循环终止之前,延迟的消息将在未来的到期时间内不传递。
从源码来分析 IntentService 的执行顺序
在onCreate()初始化HandlerThread和ServiceHandler,用于在后面调用onStart后来发送消息。
@Override
public 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);
}
每次启动服务都会调用一次onStartCommand()方法,并且它会调用onStart()
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
在onStart()中发送消息
@Override
public void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);
}
后台任务是顺序执行的
因为 Handler 中的 Looper 是顺序处理消息。
任务执行完成之后结束服务:
private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);// 使用 stopSelf(msg.arg1); 而不使用 stopSelf();// 是因为 stopSelf() 会立即停止服务,// 而 stopSelf(msg.arg1); 在停止服务前会先判断最近启动服务的次数是否和 startId 相等// 如果相等就历经停止服务,不想动则不停止服务stopSelf(msg.arg1);}
}
IntentService 使用
创建一个实例继承自 IntentService
public class TestIntentService extends IntentService {private static final String TAG = "TestIntentService";public TestIntentService() {super(TAG);Log.e(TAG, "TestIntentService: " );}@Overridepublic void onCreate() {super.onCreate();Log.e(TAG, "onCreate: " );}@Overrideprotected void onHandleIntent(@Nullable Intent intent) {String taskAction = intent.getStringExtra("task_action");SystemClock.sleep(3000);Log.e(TAG, "onHandleIntent: "+taskAction);}@Overridepublic void onDestroy() {Log.e(TAG, "onDestroy: service destory" );super.onDestroy();}
}
注册服务
在AndroidMainfest.xml中注册服务
<service android:name=".thread.TestIntentService"/>
开启服务
Intent intent = new Intent(CallBackTestActivity.this, TestIntentService.class);
intent.putExtra("task_action","com.dx.action.TASK1");
// 开启第一个服务
startService(intent);
intent.putExtra("task_action","com.dx.action.TASK2");
// 开启第二个服务
startService(intent);
intent.putExtra("task_action","com.dx.action.TASK3");
// 开启第三个服务
startService(intent);
输出结果是:
从截图中的时间,以及输出顺序正好验证了上面的叙述!ok,完工~
原创作者:龙衣袭,原文链接:https://www.jianshu.com/p/92c8a4451bb0
欢迎关注我的微信公众号「码农突围」,分享Python、Java、大数据、机器学习、人工智能等技术,关注码农技术提升•职场突围•思维跃迁,20万+码农成长充电第一站,陪有梦想的你一起成长。
异步处理老司机:IntentService 源码分析相关推荐
- Android面试题Service,Android面试题-IntentService源码分析
自定义控件 联网 工具 数据库 源码分析相关面试题 Activity相关面试题 Service相关面试题 与XMPP相关面试题 与性能优化相关面试题 与登录相关面试题 与开发相关面试题 与人事相关面试 ...
- Android 异步处理之IntentService源码分析
本文授权发布公众号[刘桂林],星球[Hi Android] 今天介绍一下IntentService,他和Service其实差不多,只是内部实现了一个HandlerThread,这点我们看源码其实就可以 ...
- 【spring】spring异步执行的使用与源码分析
在实际的开发过程中,有些业务逻辑使用异步的方式处理更为合理.比如在某个业务逻辑中,需要把一些数据存入到redis缓存中,这个操作只是一个辅助的功能,成功或者失败对主业务并不会产生根本影响,这个过程可以 ...
- 网络编程之 哈希表原理讲解 来自老司机的源码
鉴于博主很久没由跟新过数据结构的内容了,所以博主打算给大家讲解一下哈希表的操作 下面的内容来自于一位老司机 martin的源码,博主在这里借用一下,目的是突出哈希表的原理,明天博主就周末了,也能腾出时 ...
- 老司机php源码,JeRuen
PHP扩展开发系列01 - 我要成为一名老司机 1. 关于扩展的教程貌似挺全了,为啥还写?记录下我写扩展的历程 自认为会写的更容易理解 我的宗旨就是 "先用再识" 代码写着写着就知 ...
- netty源码分析系列——EventLoop
2019独角兽企业重金招聘Python工程师标准>>> 前言 EventLoop也是netty作为一个事件驱动架构的网络框架的重要组成部分,netty主要通过它来实现异步编程,从前面 ...
- Android HandlerThread 源码分析
HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我们又有一 个耗时任务需要执行,我们不得不重新创建 ...
- OkHttpClient源码分析(一)—— 同步、异步请求分析和Dispatcher的任务调度
OkHttpClient同步请求的执行流程和源码分析 同步请求示例 OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout ...
- 【OkHttp】OkHttp 源码分析 ( 同步 / 异步 Request 请求执行原理分析 )
OkHttp 系列文章目录 [OkHttp]OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 ) [OkHttp]Android 项目导入 OkHttp ( 配置依赖 | 配置 ...
- Thrift异步IO服务器源码分析
http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html 最近在使用 libevent 开发项目,想起之前写 ...
最新文章
- 周志华:严肃的研究者就不该去触碰强人工智能
- python和c哪个适合入门-编程入门选什么语言好?C 语言还是Python ?为你解析
- C++学习笔记第二天:几个知识点
- Linux查看文件内容命令:cat, tail, head, more, less
- java写的教育管理的项目_干货分享|推荐12款适合做Java后台管理系统的项目
- homeassistant mysql_HomeAssistant学习笔记docker安装的ha更换数据库
- GitHub和Microsoft TFS对比有什么优势
- 如何使用计算机中的导出,(excel在电脑的哪个文件里?)excel怎么把查找的导出
- [置顶] Embedded Server:像写main函数一样写Web Server
- 【两种方式】用python和ENVI画出高光谱遥感影像的3D立体图
- vscode推荐编程字体
- Python-爬取历史地震数据并可视化
- mysql 唯一约束和唯一索引_谈谈唯一约束和唯一索引
- Centos7安装Docker,阿里源,网易镜像
- 51单片机入门学习------环境搭建
- Oracle卸载的全过程
- WordArt与everything联用生成含中文的词云
- Java读取txt文件,并且对其文件内容进行统计排序
- 谷歌app使用的是什么字体_Google字体无法在中国使用-如何修复
- 华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典
热门文章
- 计算机速录学什么,学速录需要哪些能力
- linux grep正则表达式,linux-正则表达式与grep命令
- 论文笔记_SLAM_VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator
- opencv数字图像处理(3)- 图像平滑与锐化
- 中缀表达式转后缀表达式(非常简单易懂)
- 安装vs2008之后系统好像变慢了?
- 钉钉自定义机器人 发送文本 换行 \n无效果
- JDBC03 利用JDBC实现事务提交与回滚【调用Connection中的方法实现事务管理】
- 0917 词法分析程序(java版)
- 如何建立开发环境可以让开发人员快捷开发出模型的原型