天天看點

IntentService分析

IntentService分析

我所有的文章都會送出到github上,喜歡的同學可以來github關注。歡迎送出你們的文章

Github https://github.com/twolight/LearnNote.git

郵箱 [email protected]

背景

Service運作在調用它的程序和線程中,在開發當中,在Activity中啟動Service,意味着Service将運作在主線程中。是以,它的onXxx方法,并不能做耗時的操作的,不然将阻塞主線程,可能導緻ARN。

一般情況,在Service做耗時操作,會在Service中另開子線程,做這部分耗時操作。幸運的是,Android提供了IntenService這個類,滿足了我們在Service中做耗時操作的要求。

分析

下面将分析IntenService内部是如何做到的。下面是主要的代碼

public abstract class IntentService extends Service{
        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);
            }
        }
        @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);
        }
        @Override
        public void onDestroy() {
            mServiceLooper.quit();
        }
        @WorkerThread
        protected abstract void onHandleIntent(Intent intent);
    }
           

在IntenService onCreate方法中,建立一個HandlerThread 線程對象并啟動起來。

看看HandlerThread的實作

public class HandlerThread extends Thread{
        ...

        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            mTid = -;
        }
        ...
    }
           

HandlerThread 确實是一個線程,果然IntentService實作也是另外開一個線程。

在這個子線程中啟動、運作的時候,建立一個Looper,并讓Loop開始從消息隊列取出消息進行處理。

public static void loop() {
        ...
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            msg.target.dispatchMessage(msg);
        }
    }
           

Looper的loop方法中,for無限循環的調用消息,通過注釋//might block,如果消息隊列為空,那麼線程會阻塞在這裡,直到有消息隊列不為空。取出來的消息如果為null,通過注釋// No message indicates that the message queue is quitting.。知道message queue正在退出,Looper就跳出循環,不在處理消息。不為null,則調用Hander的dispatchMessage方法。

Looper/Handler知識,請看我的另外一篇文章

Looper Handler MessageQueue分析

IntentService onCreate方法中,啟動啟動線程之後,獲得這個子線程的Looper,并且将它與ServiceHandler這個Handler綁定。

那我們就知道了,ServiceHandler其實是用來向子線程發送消息的。子線程通過Looper,去周遊消息隊列,取出消息,回調ServiceHandler的handleMessage方法,進而調用onHandleIntent方法。onHandleIntent方法,就是需要我們自己實作的耗時操作。

總結

  • IntentService建立時

    建立一個Hander和子線程,handler與子線程的Looper綁定。線程run方法中,Looper一直循環等待處理消息。是以子線程不會退出,一直等待消息的到來。

  • IntentService啟動時

    通過Handler向子線程發送消息,子線程周遊消息隊列,發現有消息,并處理消息,調用handleMessage方法,handleMessage方法調用onHandleIntent方法。onHandleIntent方法中我們實作自己的耗時操作。也就是說耗時操作,是在子線程運作的,并不會阻塞主線程。另外,onHandleIntent調用完接着會調用stopSelf(msg.arg1)方法,停止IntentService。系統回調onDestroy方法,讓子線程的Looper退出,不在循環處理消息。子線程的run方法也就調用完畢,子線程自己結束釋放線程資源。