IntentService详解

问题背景:

       我们知道,在context里启动一个服务的时候,其实服务是在主线程运行的,所以服务里着实不能进行耗时操作,以免ANR。虽然服务里面不能直接进行耗时的操作,但是我们可以在服务里面的具体方法里开启子线程执行耗时任务。服务一旦运行,想让服务执行的操作已经结束,服务的使命已经达到了,但是服务的状态仍然是运行状态,除非有人为代码干预,如stopSelf()或在context里执行stopService(intent)。

解决方案:

       其实android源码已经提供了一个IntentService类,该类提供两个主要功能,一个是将服务的逻辑运行在子线程,另一个是结束逻辑时会结束服务,这个我会在源码解析中点出来,我先介绍一下如何使用该类,再介绍内部详情。

 

使用篇:

用的时候直接继承IntentService,然后重写里面的onHandleIntent方法。如下图一所示,第一步需要在无参构造里显示调用父类有参构造,为什么呢?(还不是因为IntentService没有无参构造),第二步,在onHandleIntent方法里重写服务的逻辑,其实onHandleIntent是运行在子线程中的,然后再重写onDestroy方法,以销毁回收服务。

 

在context里调用一句代码即可启动服务,startService(new Intent(this,MyIntentService.class)); 

 

详情分析:

主要弄清楚两点1.为什么onHandleIntent工作在子线程里面,2.为什么可以自动结束服务。

如上图1.startService的时候,其实先调用的是Service生命周期里的onCreate方法,可以看到先创建了一个HandlerThread线程,然后启动了该线程,初始化了mServiceLooper和对应的Handler,我们先看看这个线程里都做了什么工作。

HandlerThread线程调用Looper.prepare()静态方法,其实是创建了Looper对象,该对象封装了消息队列和当前工作线程,下面同步代码块里的mLooper接受的就是这步创建的Looper对象。

主线程onCreate里的HandlerThread子线程启动后运行后,并不影响执行其他主线程的代码thread.getLooper(),该方法先判断当前线程是否活跃,然后在同步代码块里判断mLooper是否为null,起到了同步堵塞的作用,保证无论先执行完run方法创建Looper对象,还是先执行getLooper方法先执行都能返回非空的Looper对象。即使主线程先执行到getLooper方法,子线程还没执行到Looper的创建,也会同步等待,知道被notifyAll(),得到非空的Looper对象。子线程创建好Looper对象,消息队列之后,就开始执行Looper.loop()方法循环遍历消息队列是否有消息。如果消息队列里没有消息,则同步阻塞直到有消息,否则通过调用handler里的dispatchMessage()方法进行message的分发,dispatchMessage()会回调相应Handler的handlerMessage()方法,而handlerMessage方法调用的是IntentService里的onHandleIntent方法,就是我们重写的这个方法。

对于消息的发送是不言而喻的,其实oncreate方法里最后初始化的mServiceHandler就是发送消息的载体Handler,只是没有在onCreate()方法里发送,其实根据服务启动的生命周期,执行完onCreate方法之后,会调用onStardCommand(),这个方法会调用本类的onStart方法,在onStart方法里才进行的消息的发送。

小结:因为在主线程里调用了开启了子线程HandlerThread,子线程创建Looper并轮询消息队列,根据消息携带的Target字段将消息分发到对应的handler处理,然后回调handler的handleMessage(Message msg),handleMessage调用onHandleIntent方法,onHandleIntent方法里就是咱们重写的服务的逻辑,到此回答了onHandleIntent为什么工作在子线程里的问题。

如上箭头所示,服务代码结束之后,调用了stopSelf(),方法结束服务,回到了第二个问题。

 

总结:IntentService是系统提供的服务封装类,大家用的时候注意里面的细节即可。

 

 

 

 

 

 

 
 
 
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值