0.前言

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52440418

IntentService是一种特殊的Service,它继承了Service,因此它自然会比单纯的线程优先级要高,然后它自己依旧是一个抽象类,需要创建自己的子类。IntentService可用于执行后台耗时任务,执行完毕后会自动停止。这是它最大的特点。

IntentService内部封装了HandlerThread和Handler,因此仍然需要先从HandlerThread讲起。

1.HandlerThread

Android API提供了HandlerThread来创建线程。官网的解释是:

//Handy class for starting a new thread that has a looper.
//The looper can then be used to create handler classes.
//Note that start() must still be called.

(1)HandlerThread继承自Thread,实际上就一个Thread,只不过它比普通的Thread多了一个Looper,对外提供自己这个Looper对象的get方法,然后创建Handler时将HandlerThread中的looper对象传入。

(2)不要忘记创建HandlerThread时必须调用其start()方法。

(3)但是需要注意的是,当activity退出了,这个HandlerThread线程并没有终止,还是在那里做looper死循环,这样随着activity的创建和退出的次数增多,这样占用系统资源的无用线程会越来越多,因此在明确不需要使用HandlerThread时,可通过quit()或者quitSafely()来终止线程执行。如下所示。

mHandlerThread.getLooper().quit();

HandlerThread的简单使用实例:

/*
*@author SEU_Calvin
*@date 2016/09/05
*/
HandlerThread handlerThread = new HandlerThread("新线程");
handlerThread.start(); //创建HandlerThread后一定要记得start()
Handler handler = new Handler(handlerThread.getLooper()){
//重写handleMessage方法处理消息
//通过handler在外部send或者post消息,就会在子线程中处理该消息
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//处理消息,执行耗时任务
}
};

使用HandlerThread的好处:

(1)如果多次使用new Thread(){...}.start()这种方式开启一个子线程,会创建多个匿名线程,降低程序执行性能。而HandlerThread是Looper的,这样便可以通过消息来多次重复使用该线程,节省开支。

(2)HandlerThread是一个很有用的类,为IntentService的实现提供了技术基础。

2.IntentService

IntentService的简单使用实例:

/*
*@author SEU_Calvin
*@date 2016/09/05
*/
public class MyIntentService extends IntentService {
public MyIntentService () {
super(“MyIntentService”);
}
@Override
protected void onHandleIntent(Intent intent) {
String action = intent.getStringExtra("action");
if ("com.seucalvin.action1".equals(action)) {
//逻辑实现第一个耗时任务
}else if("com.seucalvin.action2".equals(action)){
//逻辑实现第二个耗时任务
}
}
@Override
public void onDestroy() {
//所有任务处理完自行结束,回调该方法
super.onDestroy();
}
}
//使用时
Intent intent = new Intent(this, MyIntentService.class);
intent.purExtra("action", "com.seucalvin.action1");
startService(intent); //第一个任务
intent.purExtra("action", "com.seucalvin.action2");
startService(intent); //第二个任务

2.1  IntentService的onCreate()

上面也提到了,IntentService内部封装了HandlerThread和Handler。这个可以通过其onCreate方法源码得到验证。

public void onCreate(){
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService ["+mName+"]");
thread.start();
mServiceHandler = new ServiceHandler(thread.getLooper());
}

从它的onCreate源码可以看出,IntentService第一次启动时,便创建了HandlerThread,并使用它的Looper来构造一个Handler对象mServiceHandler,这样的话,通过mServiceHandler发送的消息最终都会在HandlerThread中执行一些后台任务。

那么消息是从哪里发出来的呢?ServiceHandler又是如何处理消息的呢?


2.2  消息的发出

每次通过startService(Intentintent)启动IntentService,onStartCommand()都会调用一次处理这个Intent,onStartCommand()又调用了onStart()方法。其中便有消息发出的细节,实现如下:

public void onStart(Intent intent, int startId){
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = started;
msg.obg = intent;
mServiceHandler.sendMessage(msg);
}

2.3  消息的处理

消息处理肯定是在ServiceHandler中进行,那么我们来看一下ServiceHandler的源码:

private final class ServiceHandler extends Handler{
//获取HandlerThread的looper
public ServiceHandler(Looper looper){
super(looper);
}
@override
public void handleMessage(Message msg){
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}

从ServiceHandler的源码可以看出,handleMessage处理消息会交给onHandleIntent()方法。通过startService(Intent intent)启动IntentService时的intent便传过来了。通过intent中的参数便可以在onHandleIntent()方法中开启不同的具体的后台任务。

那么onHandleIntent必然是抽象方法,需要我们在实例里具体实现处理逻辑。

最后通过stopSelf(int startId)来等待所有消息都处理完才停止服务(调用stopSelf()方法会立即停止服务),其中startId代表启动服务的次数,由系统生成,在其参数startId跟最后启动该service时生成的ID相等时才会执行停止服务。

总结一下,IntentService有以下特点:

(1)不需要调用stopSelft()主动结束服务。在所有的intent被处理完后,系统会自动关闭服务。

(2)多个后台任务同时存在时,因为Looper是顺序处理消息的,所以IntentService会按照发起任务顺序排队执行。

(3) 继承IntentService的类至少要实现其构造方法和onHandleIntent()方法。

至此关于HandlerThread以及IntentService的解析结束。

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52440418

Android开发——HandlerThread以及IntentService详解的更多相关文章

  1. Android开发——事件分发机制详解

    0. 前言   转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52566965 深入学习事件分发机制,是为了解决在Android开发中 ...

  2. Android开发 ExpandableListView 可折叠列表详解

    前言 在需要实现一个List的item需要包含列表的时候,我们就可以选择ExpandableListView. 其实这个View的原始设计还是ListView的那套.就是增加2层的ListView而已 ...

  3. Android开发:程序目录结构详解

    HelloWorld程序的目录结构概述 我们可以在文件夹中看到,HelloWorld程序的目录主要包括:src文件夹.gen文件夹.Android文件夹.assets.res文件夹. AndroidM ...

  4. Android开发之位置定位详解与实例解析(GPS定位、Google网络定位,BaiduLBS(SDK)定位)

    在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便.定位一般分为三种发方案:即GPS定位.Google网络定位以及基站定位 最简单的手机定位方式当然是通过GP ...

  5. Android 开发 MaterialDialog框架的详解

    前言 开始之前还是需要废话一下,因为有一些坑需要告知.首先MaterialDialog在GitHub上作者已经转型使用100% Kotlin语言编写,虽然可以在Java里调用Kotlin使用.但是个人 ...

  6. Android 开发 存储目录的详解

    简介 Android设备,有3个地方的文件存储位置,他们分别是: 内部存储空间(用户无法浏览到此目录) 外部存储空间(就是手机自身的文件管理目录,用户可以浏览) SD卡的存储空间(需要插入T卡) Sh ...

  7. android 开发 View _5_ Paint详解

    转载:http://blog.csdn.net/abcdef314159 //Paint的setStyle,Style共有3种 setStyle(Style style) Paint.Style.FI ...

  8. Android开发之线性布局详解(布局权重)

    布局权重 线性布局支持给个别的子视图设定权重,通过android:layout_weight属性.就一个视图在屏幕上占多大的空间而言,这个属性给其设 定了一个重要的值.一个大的权重值,允许它扩大到填充 ...

  9. Android开发——Activity启动模式详解

    1. Activity的启动模式 本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52054893 1.1 Standard标 ...

随机推荐

  1. 韦东山笔记之用busybox构建根文件系统

    1 百度搜索busybox进入busybox官网(https://busybox.net/)作者:恒久力行 QQ:624668529  点击左侧DownloadSource下载最新稳定版的busybo ...

  2. vue-elem-stylus 的mixin用法

    .tab border-1px{red} minxin border-1px(&color) position:relative &::after display:block posi ...

  3. C/C++ sort函数的用法

    sort函数的用法(#include<algorithm>) 做ACM题的时候,排序是一种经常要用到的操作.如果每次都自己写个冒泡之类的O(n^2)排序,不但程序容易超时,而且浪费宝贵的比 ...

  4. Azure School,让系统化学习回归一站式的简单体验

    承认吧,「终身制学习」已经成为一个不可抵挡的趋势.不管你从事什么行业,几乎已经没有什么可以一直吃老本就能搞定的事情,总有各种新的技术和概念等着你去学.至于发展速度飞快的IT 技术,不断的学习更是贯彻始 ...

  5. thinkphp 3.2.3版本学习笔记

    2.开启调试模式,有什么作用?(默认关闭,在ThinkPHP.php 33行左右) (1)非法调用的时候,有详细的报错信息,便于调试 (2)APP_DEBUG为true并且缓存文件存在,走缓存文件,否 ...

  6. java Vamei快速教程18 容器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java中有一些对象被称为容器(container).容器中可以包含多个对象,每个 ...

  7. IOS CALayer基本使用 (图层)

    ● 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层(CALayer) ● 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView 的l ...

  8. django建议入门-FYI

    django 简易博客 现在正式开始博客开发 1安装官方发布版 官方发布的版本带有一个版本号,例如1.0.3或1.1,而最新版本总是可以在http://www.djangoproject.com/do ...

  9. spark dataframe函数编程

    DataFrame 的函数 Action 操作 1. collect() ,返回值是一个数组,返回dataframe集合所有的行 2. collectAsList() 返回值是一个Java类型的数组, ...

  10. 【BZOJ4196】[NOI2015] 软件包管理器(树链剖分)

    点此看题面 大致题意: 有\(n\)个软件包,它们的依赖关系形成一棵树.现在,问你安装或卸载一个软件包,会影响多少个软件包的安装状态. 树链剖分 这道题应该是 树链剖分 算法比较入门的题目吧. 对于安 ...