Android IntentService源码解读
来源:互联网 发布:淘宝联盟点击数0 编辑:程序博客网 时间:2024/05/16 05:27
说到IntentService,其实他内部也是一个Thread + Handler实现的,之前我们在阅读源码,让你彻底理解AsyncTask运行原理这篇中我们就说过,他的原型其实也是Thread+Handler,对吧。只不过这个Thread有点特别,怎么个特别法呢?这个线程run()方法执行是获取创建Looper的操作,而平常呢,我们看看线程run()方法里,一般是执行一些耗时操作的对吧,比如我Asynbctask里面就是这样的。好了,不多说,下面我们来阅读阅读IntentService的源码。
IntentService是一种特殊的Service,他继承了Service,而且它还是一个抽象类,因此,你作为一个开发者,就必须是他的子类才能使用它,顺便还说一句,有的面试官会问你,抽象类能不能继承非抽象类,那么你看了IntentService这个类,那你的回答又会是什么呢?哈哈!答案显而易见,是可以的,对不?IntentService可用于执行后台的耗时操作,而且当他执行完相关的任务时,他就会停止自己,这也是Google官方给出优化应用内存中的一种方法。这个道理也很明显,当你不需要一个常驻后,让他执行完他的任务之后,就释放内存,节省内存开销,这对一个开发者来说,是一个良好的习惯。好,我们先来看看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); }
你看看,他里面做了什么?首先,这onCreate()方法里创建了一个HandlerThread线程,这个HandlerThread里面做了什么,你暂时不要管,如果你想知道,你可以去先去看看这篇关于HandleThread的源码解读HandleThread源码分析,其实HandlerThread主要的事情就是构造一个Looper实例,通过它得到这个Looper实例,通过Looper来构造一个ServiceHandler实例,那么,通过这个mServiceHandler发送的消息始终会在ServiceHandler里面去执行,当然,它也可以用于执行后台的任务,每次启动IntentService时,它的onStrartCommand()方法都会被调用一次,IntentService在onStartCommand()方法中处理每一个后台任务的Intent,下面我们看看,onStartCommand()中是如何处理外部的Intent的,它内部调用了onStart()方法,那我们就来看看onStart()方法内部的实现,如下所示:
@Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } /** * You should not override this method for your IntentService. Instead, * override {@link #onHandleIntent}, which the system calls when the IntentService * receives a start request. * @see android.app.Service#onStartCommand */ @Override public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }从上面代码可以看出,IntentService仅仅是通过mService发出一个消息,这个消息会在ServiceHandler中处理,mServiceHandler收到消息后,它会把这个Intent对象传递给onHandleIntent()方法去处理。注意,这里这个Intent对象跟你外部传来的Intent对象完全一致,通过这个Intent对象就可以解析在外部启动IntentService所传过来的相关参数,然后你通过这些参数就能区分具体的后台任务,这样在onHandleIntent()方法中就可以对不同的后台人物做处理了。当onHandleIntent()方法执行完之后,它就会调用stopSelf(int startId)方法来停止掉服务,那么这里采用stoptSelf(int startId)而不采用stopSelf()方法,那是因为,stopSelf()方法会立刻将服务停止掉,假如说某个时候,还有消息未处理,那怎么办?如果你调用stopSelf()方法的话,那么后面的消息,你将无法处理,这样,对我们来说是我们不想要的,而onStopSelf(int startId)就能帮我们解决这个问题,这个方法呢,会等待所有的消息处理完,才会将服务停止掉。
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); } }
我们知道,onHandleIntent()方法是一个抽象方法,在Java中,如果某个类有抽象方法那么这个类必须声明为抽象,抽象类中可以有抽象方法,也可以有实现的方法,所以呢,这个类是抽象类,那么我们就需要子类来实现这个抽象方法,他的作用是从Intent区分具体的任务并执行这些任务。如果当前后台之后一个任务,那么onHandleIntent()方法执行完成之后,服务就会停止掉,如果此时后台有多个任务时,那么当onHandleIntent执行完最后一个任务时,才会将服务停止掉。在IntentService中,我们执行一个后台任务,就需要启动一次IntentService,而IntentService内部又是通过消息的方式想HandleThread来请求执行任务的,而这个Looper中取出消息的消息也是有序的,那么我就可以猜测出,他的任务也是按照你启动IntentService的后台任务的顺序来执行的。如果有对Handler内部机制不熟的,可以看看这篇阅读源码,让你彻底理解Handler、Message、Looper之间的关系博文。
下面,我们将通过一个例子来说明当需要在后台执行多个任务的情况,到底是不是要执行完所有的任务之后,才回去停掉服务。代码如下:
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService(){ super(TAG); } @Override protected void onHandleIntent(Intent intent) { String action = intent.getStringExtra("task_action"); Log.e(TAG, "receive task" + action); SystemClock.sleep(5000); if("com.qhb.action.TASK1".equals(action)){ Log.e(TAG,"handle task : "+action); } } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG,"service destroyed"); }
实践结果,我就不贴了,不知道android studio为毛突然打印不出日志了,没法演示了,不过,大家可以自己动手试试。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this,MyIntentService.class); intent.putExtra("task_action", "com.qhb.action.TASK1"); startService(intent); intent.putExtra("task_action","com.qhb.action.TASK2"); startService(intent); intent.putExtra("task_action","com.qhb.action.TASK3"); startService(intent); intent.putExtra("task_action", "com.qhb.action.TASK4"); startService(intent); }}
具体的都给贴上了,大家只要创建工程,复制黏贴到里面即可运行,非常不好意思,并不是我偷懒,不知道studio出什么毛病了。
这里顺便说一下,Service与IntentService的区别就是能否执行耗时操作而已。
欢迎大家拍砖、吐槽。
- Android IntentService源码解读
- android IntentService Service HandlerThread 源码解读
- IntentService源码解读
- android IntentService解读
- IntentService意图服务 源码解读
- Android IntentService 源码解析
- android-----IntentService源码分析
- Android IntentService源码解析
- Android IntentService源码分析
- <Android源码>IntentService源码解析
- Android之IntentService源码浅析
- 【Android】IntentService & HandlerThread源码解析
- Android 看IntentService源码延伸
- Android线程IntentService源码分析
- 【Android】IntentService & HandlerThread源码解析
- 【Android应用源码分析】IntentService 源码分析
- Android IntentService浅谈以及源码分析
- Android开发:IntentService使用(源码分析)
- 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径
- LeetCode之Breadth-first Search题目汇总
- hadoop集群ambari搭建(2)之制作hadoop本地源
- iOS button.titleLabel和直接设置button setText
- 各种语音算法应用场景
- Android IntentService源码解读
- oc的Runtime
- java.lang.OutOfMemoryError: PermGen space及其解决方法
- Oracle GoldenGate 学习教程一:介绍和安装
- Spring - Aop简单的mvc示例 和 Aop注解的使用
- Java工具类--读取Properties文件
- C++强制类型转换
- 欢迎使用CSDN-markdown编辑器
- 黑马程序员--OC自学笔记---10Foundation、NSString、NSURL、NSRange、NSArray、NSMutableArray、NSDictionary