IntentService源码分析
来源:互联网 发布:ubuntu ports 源 编辑:程序博客网 时间:2024/06/06 01:15
IntentService继承了Service并且是一个抽象类,需要创建它的子类才能使用IntentService。它相对Service来说,是一个特殊的Service,它的内部使用HandleThread
来执行服务,任务执行完,IntentService会自动退出。相对于Thread来说,它是一个服务,它的优先级高于线程,不容易被系统回收。
一个面试问题:我要用服务下载apk,是用IntentService,还是Service好?为什么?
IntentService与Service都可以执行下载apk的任务。具体的下载代码可以观看我的文章:IntentService、Service下载的apk。在回答这可问题之前我们要再次回顾一下Service的概念。Service是一种计算型组件,用于在后台执行一系列计算任务。Service不是一个线程,尽管它是执行后台计算的,它是运行在主线程中,耗时的后台操作仍然需要在单独的子线程中去执行,所以不要在Service的onStart方法中执行耗时操作,不然会出现Application Not Responding!的异常。而IntentService采用队列的方式将请求的Intent加入队列,然后开启一个线程来处理队列中的Intent,对于异步的startService请求。IntentService处理完一个后再处理第二个,都是在子线程中,不会阻塞主线程。所以有耗时操作与其在Service里开启子线程不如在IntentService中处理耗时操作。
回到主题,继续分析IntentService。
在IntentService的onCreate()方法中,可以看到它实现了HandleThread 和Handle。
private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; @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); }
IntentService第一次启动时,onCreate()方法调用,创建一个HandlerThread,获取到mServiceLooper,mServiceHandler。通过mServiceHandler发送信息会在HandlerThread中执行。每次启动IntentService,会调用onStartCommand()。IntentService在onStartCommand()方法中处理后台的Intent。在源码中onStartCommand调用了onStart():
@Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
IntentService通过mServiceHandler发送了一条信息,消息会在HandleThread方法中处理。同时将Intent对象给 ServiceHandler的onHandleIntent方法处理。onHandleIntent是运行在子线程中,可以做耗时操作。另外这里的Intent对象和外界startService(intent)保持一致,通过它可以获得外界启动IntentService传递的参数,可以区分具体的后台任务,对不同的后台采取不同的处理方式(可以咱参照文章后边的样例)。onHandleIntent方法执行完之后,会调用stopSelf(int startId)停止服务。stopSelf()会立即停止服务,stopSelf(int startId)会等待所有信息都处理完后才关闭服务,它在服务关闭前会判断最近启动的次数是否与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); } }//This method is invoked on the worker thread with a request to process. @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent);
onHandleIntent是一个抽象方法,需要在子类中实现,它的作用就是区分Intent中的参数来区分任务并执行。在执行完onHandleIntent方法后,如果目前只有一个后台任务会立刻调用stopSelf(int startId)停止服务。如果有多个,会在onHandleIntent执行完最后一个任务后调用停止服务。每执行一个后台任务都会启动一次IntentService,而IntentService内部的信息是通过HandleThread来执行,Handle中的Looper顺序处理信息,所以IntentService是顺序执行后台任务的。多后台任务会按照外界发起的顺序排队执行。
public class DemoIntentService extends IntentService { static final String Tag = "DemoIntentService"; public DemoIntentService() { super("demo-intentService"); } @Override protected void onHandleIntent(Intent intent) { String action = intent.getStringExtra("test_action"); Log.e(Tag, "receive action=====" + action); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void onDestroy() { Log.e(Tag, "onDestroy====="); super.onDestroy(); }}
public class TestActivity extends Activity { BroadcastReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);Intent mIntent = new Intent(this, DemoIntentService.class); mIntent.putExtra("test_action","action1"); startService(mIntent); mIntent.putExtra("test_action","action2"); startService(mIntent); mIntent.putExtra("test_action","action3"); startService(mIntent); }}
注册列表<service android:name=“.downloadApk.DemoIntentService"/>
打印结果:
05-16 23:53:12.219 18007-18292/? E/DemoIntentService: receive action=====action1
05-16 23:53:13.219 18007-18292/? E/DemoIntentService: receive action=====action2
05-16 23:53:14.219 18007-18292/? E/DemoIntentService: receive action=====action3
05-16 23:53:15.219 18007-18007/? E/DemoIntentService: onDestroy=====
日志显示三个后台任务顺序执行,在action3后,执行stopSelf(int startId)。
=====================================>
这是一篇对书笔记,文章内容大多数来自于androdi开发艺术探索,很不错的一本书。
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- 从源码分析IntentService
- IntentService源码分析
- IntentService源码分析
- IntentService 源码分析
- IntentService 源码分析
- intentservice源码分析
- android-----IntentService源码分析
- IntentService的源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- 微信小程序:toast的使用
- js中的数组方法
- 路由和模板引擎的使用
- U-Boot的设备管理
- CSDN日报20170516 ——《 驱动小白和硬件老司机关于硬件那点事儿的一次密谈》
- IntentService源码分析
- 表单防止页面重复提交方法
- JS中比较日期大小
- Java对象的浅克隆和深克隆
- Centos7中安装tomcat7
- Sass嵌套时调用父选择器
- IPC之消息队列
- 入门 Webpack,看这篇就够了
- 五分钟理解Java的反射API