Android查缺补漏(线程篇)-- IntentService的源码浅析
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8975114.html
在Android中有两个比较容易弄混的概念,Service和Thread,我们都知道这两个东西都可以执行后台任务,但要注意的是Service是跑在主线程中的,如果不做特殊处理是会阻塞主线程的,而IntentService正好弥补了这一点,在《Android查缺补漏--Service和IntentService》这篇博文中已经简单介绍过了IntentService的基本用法,本篇博文会将对IntentService的原理做一个简单的分析。
一、IntentService的初始化分析
IntentService是一种服务,可以很方便的执行后台异步任务,采用HandlerThread执行任务,当任务执行完毕后,IntentService自动退出。
相比于普通的Service,IntentService继承了Service,并在其内部创建了HandlerThread和Handler,其中HandlerThread用于执行耗时任务,可以查看IntentService的onCreate方法的源码:
@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);
}
通过源码可以看到,IntentService在onCreate()方法中创建了一个HandlerThread,并为这个HandlerThread绑定了一个Handler(ServiceHandler)。
注:HandlerThread 是一种具有消息循环的线程,在其内部可以使用handler,其底层实现是内部创建了Looper的线程。
二、IntentService启动任务过程分析
外界首次调用startService方法来启动IntentService时,就会触发onCreate()方法,完成上面操作。
当外界每次触发onStart方法时,就会在此方法里面通过ServiceHandler向HandlerThread线程发送消息,onStart方法的源码如下:
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
当上面源码中的mServiceHandler.sendMessage方法发送完消息后,在ServiceHandler的handlerMessage方法中就会调用onHandleIntent方法来执行我们创建的异步任务,当执行完onHandleIntent中的代码就会使用stopSelf(msg.arg1)尝试关闭Service。
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
由于HandlerThread只是一个单线程,所以是串行处理任务。
(stopSelf():立即停止服务。stopSelf(int startId):尝试停止服务,当还有其他消息未处理,会等待其他消息处理完后再关闭)
三、IntentService优势
- 由于IntentService是一个服务,所以在执行后台任务时不容易被杀死,想比而言单纯的开启一个线程来执行后台任务,由于这个进程中没有活动的四大组件,所以非常容易被系统杀死。
- 其实在普通的Service中开启一个线程也能达到IntentService的效果,只是这样我们用起来更方便,那么在Service中开启线程或者使用IntentService相比在Activity中开启线程有什么优势呢?在Activity中开启了线程后,当退出了Activity时如果线程中的任务没有执行完毕,线程是不会退出的。而此时再打开同一个Activity又会创建一个新的线程,就是说在Activity中创建的线程不会随着Activity的销毁而销毁,是不可控的。而如果我们在Service中创建了线程,然后如果线程中的任务没有执行完毕,我们可以让Service一直运行在后台去承载这个线程,这样的话我们以后在想操作这个线程的话就可以在外界通过bindService的方式再绑定这个Service,从而可以控制运行在这个Service中的线程。
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8975114.html
本文为博客园首发并已同步授权给腾讯云·云+社区!
Android查缺补漏(线程篇)-- IntentService的源码浅析的更多相关文章
- Android查缺补漏--Service和IntentService
Service的运行不依赖界面,即使程序被切换到后台,Service仍然能够保持正常运行.当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行. Service 分为启动状态和绑定 ...
- Android查缺补漏(View篇)--自定义 View 的基本流程
View是Android很重要的一部分,常用的View有Button.TextView.EditView.ListView.GridView.各种layout等等,开发者通过对这些View的各种组合以 ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
- Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8425736.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(View篇)--事件分发机制源码分析
在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...
- Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android查缺补漏(线程篇)-- AsyncTask的使用及原理详细分析
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8515304.html 一.AsyncTask的使用 AsyncTask是一种轻 ...
随机推荐
- redis中的aof模式,产生的是增量数据,还是全量数据?
先说答案:全量数据. 1.修改redis.conf,开启rdb,禁用aof 上面这个是持久化文件的路径,我们ll看下: 2.启动redis后,cli查看里面的key [root@mini1 redis ...
- HTML初识
HTML初识 web服务本质 import socket def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) so ...
- Hibernate(四):Hello World
下载hibernate开发包: 在本章之前需要继承hibernate开发插件到eclipse,详细操作请参考我的博文:<Hibernate(一):安装hibernate插件到eclipse环境& ...
- python自带的web服务器
python自带的web服务器 python自带的包可以建立简单的web服务器 BaseHTTPServer 提供基本的web服务和处理类 SimpleHTTPServer 包含执行get请求的Sim ...
- [转]Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法
使用Python写文件的时候,或者将网络数据流写入到本地文件的时候,大部分情况下会遇到:UnicodeEncodeError: 'gbk' codec can't encode character ' ...
- Node.js+Koa开发微信公众号个人笔记(三)响应文本
响应输入文本和响应事件类似,首先对微信服务器发送来的数据的MsgType进行处理,如果是text,说明是文本,接下来可以对文本内容进行处理,比如用户输入了1,可以给用户回复一个文本或者图文或者视频等信 ...
- spring加载xml的六种方式
因为目前正在从事一个项目,项目中一个需求就是所有的功能都是插件的形式装入系统,这就需要利用Spring去动态加载某一位置下的配置文件,所以就总结了下Spring中加载xml配置文件的方式,我总结的有6 ...
- Spring-cloud (一):Eureka注册中心搭建
前提 系统安装jdk1.8及以上,配置好maven的ide(这里用idea进行演示,maven版本3.5,配置阿里云源) 项目搭建 新建一个maven项目,创建最简单的那种就好,项目名这里为Eurek ...
- string[] 清理重复+反转显示
string[] listUrl = String.Join(",", list.Replace("\r\n", ",").Split(', ...
- hash详解
首先介绍一下hash? 事实上是一种叫做蛤丝的病毒 hash的做法: 首先设一个进制数base,并设一个模数mod 而哈希其实就是把一个数转化为一个值,这个值是base进制的,储存在哈希表中,注意一下 ...