IntentService源码解析
来源:互联网 发布:c语言教学视频小甲鱼 编辑:程序博客网 时间:2024/06/13 07:08
一、简介
IntentService是作为处理异步请求的基类(以Intent对象表示),客户端发送请求, 通过android.content.Context.startService(Intent)的 方式把请求传递给IntentService。根据需要启动服务,依次使用线程池处理每个传过来Intent请求所对应的任务。
这样可以避免事务处理阻塞主线程(ANR)。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。
以上是IntentService的官方定义,接下来我们来讲讲IntentService的特别之处,以及它跟Service又有什么联系和区别呢?
其实IntentService是一个具有消息循环特点的Service,它本身就是一个Service(继承自Service),Service有的特性它都有,当然,它也有Service没有的特性,这就是本篇博客要讨论的重点。我们需要知道:Service其实是在主线程中的,它在执行onCreate方法后打印的线程id就是主线程id,这就是说,如果你要在Service中编写耗时操作的话,程序很有可能会出现ANR的,这时候Android就给我们讲设计了IntentService这个东西~
话不多说,轻轻地直接抛出一个栗子吧:
- 定义IntentService
/** * 自定义IntentService */public class MIntentService extends IntentService{ public MIntentService() { super(""); } @Override protected void onHandleIntent(Intent intent) { Log.i("tag", intent.getStringExtra("params") + " " + Thread.currentThread().getId()); }}
- 在AndroidManifest中注册Service
<service android:name=".MIntentService" />
- 启动这个Service
/** * 定义TextView点击事件,启动IntentService服务 */title.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, MIntentService.class); intent.putExtra("params", "ceshi"); startService(intent); } });
打印结果显示,可以发现当点击title组件的时候,service接收到了消息并打印出了传递过去的intent参数,同时显示onHandlerIntent方法执行的线程ID并非主线程,这是为什么呢?接下来就是源码的解析。
二、源码解析
IntentService源码:
public abstract class IntentService extends Service { private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { //在工作线程中调用onHandleIntent,确保onHandleIntent不会阻塞主线程 onHandleIntent((Intent)msg.obj); //在执行完了onHandleIntent之后,我们需要调用stopSelf(startId)声明某个job完成了 //当所有job完成的时候,Android就会回调onDestroy方法,销毁IntentService stopSelf(msg.arg1); } } public IntentService(String name) { super(); //此处的name将用作线程名称 mName = name; } public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { super.onCreate(); //创建HandlerThread,利用mName作为线程名称,HandlerThread是IntentService的工作线程 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); //将创建的HandlerThread所绑定的looper对象传递给ServiceHandler, //这样我们创建的Handler就和HandlerThread通过消息队列绑定在了一起 mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { //在此方法中创建Message对象,并将intent作为Message的obj参数, //这样Message与Intent就关联起来了 Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; //将关联了Intent信息的Message发送给MessageQueue mServiceHandler.sendMessage(msg); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { //IntentService重写了onStartCommand回调方法:在内部调用onStart回调方法 //所以我们在继承IntentService时,不应该再覆写该方法,即便覆盖该方法,我们也应该调用super.onStartCommand() onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { //在onDestroy方法中调用了Handler的quit方法,该方法会终止消息循环 mServiceLooper.quit(); } @Override @Nullable public IBinder onBind(Intent intent) { return null; } @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent);}
首先我们要用IntentService就要重写它的抽象方法:onHandleIntent(),该方法是运行在子线程中的,为什么这么说呢?查看源码我们可以知道,当onCreate方法调用时,创建了一个IntentService的工作线程HandlerThread,取出工作线程中的Looper对象,并把它交给ServiceHandler处理,实例化ServiceHandler对象,该对象是一个继承了Handler的对象,消息的处理就是在这里面进行,同样,它用的方式是handleMessage()方法处理消息的。handler对象是依附于HandlerThread线程的,所以其handeMessage方法也是在HandlerThread线程中执行的,从而证实了我们刚刚例子中的一个结论。onHandlerIntent在子线程中执行。
那么发送消息有是在哪里呢?我们看onStart()方法,该方法关联了Message和Intent,并把Intent对象作为Message参数,并一起打包发送给MessageQueue。
三、总结
至此,IntentService发工作机制就已经很清晰了,它不过就是运用了消息队列机制来处理Intent对象的Service罢了~
下面我们用一张图简单地展示下:
结论:
IntentService是一个service,也是一个抽象类;
继承IntentService需要实现其onHandlerIntent抽象方法;
onHandlerIntent在子线程中执行;
IntentService内部保存着一个HandlerThread、Looper与Handler等成员变量,维护这自身的消息队列;
每次IntentService后台任务执行完成之后都会尝试关闭自身,但是当且仅当IntentService消息队列中最后一个消息被执行完成之后才会真正的stop自身;
- IntentService源码解析
- IntentService 源码解析
- Android IntentService 源码解析
- IntentService从源码解析
- Android IntentService源码解析
- IntentService源码解析
- IntentService源码解析
- IntentService源码解析
- <Android源码>IntentService源码解析
- 源码解析IntentService的好处
- 【Android】IntentService & HandlerThread源码解析
- 【Android】IntentService & HandlerThread源码解析
- IntentService使用及源码解析
- IntentService与HandlerThread源码解析
- Android IntentService的使用与源码解析
- Android源码解析之(五)-->IntentService
- Handler与HandlerThread、IntentService源码解析
- IntentService执行耗时任务及源码解析
- BootStrap Validator插件与KindEditor富文本编辑器冲突时的解决方法
- KUDU-Got out-of-order key column: name: "ID" type: STRING is_key: true is_nullable: false
- [BZOJ4888][洛谷3760]异或和 树状数组
- 移动端页面上下滑动,大小、透明度的变化视觉差异效果切换页面
- 20170925
- IntentService源码解析
- 新的开始
- java8时间API
- python 模糊匹配
- 实例化需求:用户故事拆分的更好线索
- Java数据结构与算法之栈_动力节点Java学院整理
- 2017大学第七~九周学习笔记
- js 获取属性值
- java之环境变量