Android中的IntentService解析
IntentService简介
IntentService是继承与Service的。所以IntentService也是一个Service,拥有Service的所有特性。
public abstract class IntentService extends Service
IntentService相比于Service有什么区别呢?IntentService可以执行一些耗时任务,并且任务完成后会服务会自动销毁。具体的源码分析如下:
//IntentService onCreate()方法public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
可以看出来在IntentService的onCreate()方法中创建了HandlerThread,并且开启了这个线程,然后创建了一个Handler对象,绑定HandlerThread的Looper对象,由此可知,IntentService异步任务的原理在HandlerThread+Handler。下面在看下onStart()方法:
//IntentService onStart()方法public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
可以看到每次开启IntentService,会调用onStart()方法,每次的意图Intent都会包装为一个Message,然后通过Handler发送到HandlerThread内部的消息队列中,并且熟悉HandlerThread的都知道其内部是构建了一个Looper的环境的。所以可以得出,IntentSerivce对于任务是顺序处理的,因为任务都会存放在HandlerThread的消息队列中,所以IntentService其实是一个单线程+消息队列的模式。那么IntentService是如何处理任务的呢?,看如下源码:
//IntentService ServiceHandlerprivate final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } }//IntentService onHandleIntent()protected abstract void onHandleIntent(@Nullable Intent intent);
可以看出每次开启IntentService,任务会被封装成一个Message,然后有Handler发送到HandlerThread的消息队列中,最终会消息对的处理会回调onHandleIntent这个抽象方法,所以需要我们重写此方法,在此方法里执行我们的耗时任务操作。那么可以注意到onHandleIntent()方法调用后会调用stopSelf()方法,那么stopSelf()的机制是怎么样的呢?
public final void stopSelf(int startId) { if (mActivityManager == null) { return; } try { mActivityManager.stopServiceToken( new ComponentName(this, mClassName), mToken, startId); } catch (RemoteException ex) { } }
可以看到执行了mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);这个方法
那么并且传递了startId这个标识,每次启动IntentService都会生成这一个标识,作为一个记录。最终会调用到ActiveServices stopServiceTokenLocked(ComponentName className, IBinder token,
int startId)方法
boolean stopServiceTokenLocked(ComponentName className, IBinder token, int startId) { if (r != null) { if (startId >= 0) { ServiceRecord.StartItem si = r.findDeliveredStart(startId, false); if (si != null) { while (r.deliveredStarts.size() > 0) { ServiceRecord.StartItem cur = r.deliveredStarts.remove(0); cur.removeUriPermissionsLocked(); if (cur == si) { break; } } } if (r.getLastStartId() != startId) { return false; } if (r.deliveredStarts.size() > 0) { Slog.w(TAG, "stopServiceToken startId " + startId + " is last, but have " + r.deliveredStarts.size() + " remaining args"); } } synchronized (r.stats.getBatteryStats()) { r.stats.stopRunningLocked(); } r.startRequested = false; if (r.tracker != null) { r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } r.callStart = false; final long origId = Binder.clearCallingIdentity(); bringDownServiceIfNeededLocked(r, false, false); Binder.restoreCallingIdentity(origId); return true; } return false; }
我们可以看到最关键的if (r.getLastStartId() != startId)不是最后一个startId就直接return false。否则将执行 r.stats.stopRunningLocked();来终止。自此这个问题终于真相大白了。
//HandlerThread onDestroy()方法public void onDestroy() { mServiceLooper.quit(); }
并且IntentService停止后会调用onDestroy()生命周期方法,内部终止了HandlerThread内部的loop循环,进而使得HandlerThread也随之结束。
IntentService的使用场景
根据以上的分析,可以得知IntentService可以用来处理耗时的后台任务,相比我们新开一个线程,它在任务完成时会主动关闭,且内部处理任务是顺序执行的,多次开启IntentService,任务会在队列中排队,依次被执行。且IntentService是服务的特性,可以相应的提高进程优先级。
更多相关文章
- Android(安卓)Studio maven-metadata.xml 卡着不动原因和解决方
- android 蓝牙源码分析
- Android: NullPointerException when using RelativeLayout with
- 一个使用openGL渲染的炫丽Android动画库
- Android(安卓)Webview js或css 替换 注入
- Android架构组件
- Android辅助功能AccessibilityService自动全选择文字粘贴模拟输
- Android开发艺术探索 - 第10章 Android的消息机制
- Android(安卓)OpenGL ES 开发中的Buffer使用