IntentService与HandlerThread源码解析

来源:互联网 发布:2017流行语言网络词 编辑:程序博客网 时间:2024/06/15 16:35

一,写在前面

       IntentService使用场景:需要在服务中执行耗时的任务,使用IntentService代替在Service中开启子线程。
       HandlerThread:封装了Thread+Looper,但并没有封装Handler。它是一个线程,run方法中初始化了Looper对象,并开启消息循环。
       IntentService:封装了HandlerThread+Handler的Service。
       在阅读本篇文章前,建议先了解Handler机制的工作原理,本篇将不再对重复内容进行阐述。可参考文章 
       Android中Looper,MessageQueue,ThreadLocal源码解析
       全面解析Android之Handler机制

二,使用IntentService

        直接上代码,IntentService是一个抽象类,首先创建一个它的子类:

public class MyIntentService extends IntentService {public MyIntentService() {super("MyIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {SystemClock.sleep(3000);String stringExtra = intent.getStringExtra("key");SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:MM:ss");String time = format.format(new Date(System.currentTimeMillis()));Log.e("wcc", "onHandleIntent _ " + stringExtra + ", time is " + time);}@Overridepublic void onCreate() {super.onCreate();Log.e("wcc", "onCreate");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);Log.e("wcc", "onStart");}@Overridepublic void onDestroy() {super.onDestroy();Log.e("wcc", "onDestroy");}}
       接下来是启动服务的代码:

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MyIntentService.class);intent.putExtra("key", "value1");startService(intent);intent.putExtra("key", "value2");startService(intent);}}

       启动了两次服务,每次存储在extra中的值都不一样。在onHandleIntent方法中执行耗时操作,并在各个生命周期方法中打印log。

       打印log如下:


       启动两次服务,onStart调用两次,onHandleIntent方法被调用两次且间隔3秒,最后onDestroy也被调用。为了解释上面这一现象,下面开始从源码角度分析IntentService工作原理。


三,HandlerThread源码分析

public class HandlerThread extends Thread {    //...code    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }    //...code    public Looper getLooper() {        if (!isAlive()) {            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    //...code}
       第8行,初始化Looper对象,并使用ThreadLocal存储该子线程的Looper。
       第10行,从ThreadLocal中取出该线程的Looper对象,并赋值给变量mLooper。
       第15行,调用Looper.loop()方法开启消息循环。
       第21行,调用HandlerThread$getLooper返回变量mLooper,也就是获取该线程的Looper对象。
       (对ThreadLocal,Looper不了解可以查看前面推荐的参考文章,这里不再重复描述)

       小结:从上面可以看出,HandlerThread并不像名称展现的那样,它并没有封装Handler,而是封装了Thread,Looper。也就是说,HandlerThread是一个开启了消息循环的子线程。
       注意:使用HandlerThread时,若不需要HandlerThread的时候,可以调用HandlerThread的quit/quitSafely方法结束消息循环,从而终止线程的执行。关于结束消息循环的原理,见文章 Android中Looper,MessageQueue,ThreadLocal源码解析 ,这里不再重复阐述。

四,IntentService源码分析

       在调用startService启动服务的时候,会调用onCreate,onStart方法。
       查看IntentService$onCreate,IntentService$onStart方法相关的源码:
    @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);    }    @Override    public void onStart(Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }
       第8行,创建HandlerThread对象,它是一个开启了消息循环的子线程。
       第9行,调用HandlerThread$start方法启动线程,HandlerThread$run方法被调用,前面已对该方法进行分析,这里不再重复阐述。
       第11行,获取HandlerThread中的Loooper对象,是一个子线程中的Looper对象。
       第12行,创建一个变量mServiceLooper构造的Handler对象。
       
       第17~19行,创建Message对象并设置字段arg1,obj的值;
       第20行,使用Handler$sendMessage方法发送消息;

       于是,查看ServiceHandler对消息的处理,查看其源码:
    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);        }    }
       第3行,调用Handler中Looper为参数的构造函数;
       第8行,调用IntentService$onHandleIntent方法;
       第9行,调用IntentService$stopSelf方法,停止服务,回调onDestroy方法。

       查看IntentService$onHandleIntent方法源码:
protected abstract void onHandleIntent(Intent intent);
       onHandleIntent是一个抽象方法,需要我们自己重写该方法,并将耗时操作放在里面。

       那么onHandleIntent为啥能执行耗时操作呢?
       通过对Handler机制的理解可以知道:调用Looper$loop方法取出消息队列里的消息,并处理消息。因此消息的处理在哪个线程中完成取决于Looper.loop()在哪被调用,前面我们知道Looper的初始化,以及开启消息循环都是在子线程HandlerThread的run方法中完成。于是消息的处理是在子线程中执行,onHandleIntent就可以执行耗时操作。

五,最后

       可以发现IntentService通过Handler机制将任务的执行,由主线程切换到Looper所在的子线程中执行。
       
       若调用多个startService启动多个耗时任务,由于内部实现基于Handler机制,Looper是按照顺序来处理消息,因此这些耗时任务将按照启动的顺序依次执行。
       
       另外,在handleMessage方法里调用stopSelf(startId)来停止服务,此外还有一个重载方法stopSelf()。区别:stopSelf(startId)停止服务,会等待消息队列里的消息全部处理完毕,再停止服务;而stopSelf()会立刻停止服务。
       




       
       






       
原创粉丝点击