淺談IntentService原理分析

什么是IntentService?

一個(gè)帶有工作線程的,并且具有任務(wù)完成會(huì)自動(dòng)停止功能的Service

一.IntentService的用法
//繼承IntentService,并取個(gè)名兒
class SampleIntentService : IntentService("SampleIntentService") {
//重寫(xiě)onHandleIntent
   override fun onHandleIntent(intent: Intent?) {
               //進(jìn)行耗時(shí)操作,這里是工作線程
   }
//別忘了在mainfest里注冊(cè)哦
}

emmmm,IntentService就這么簡(jiǎn)單,不過(guò)這只是用法哦。

二.IntentService結(jié)構(gòu)組成

要想了解源碼,別單單看別人的技術(shù)文章,看是沒(méi)有用的,最好把源碼打開(kāi),邊看邊對(duì)著源碼了解,那樣能理解的快些。
1.看看繼承類

這里看到IntentService是繼承Service
public abstract class IntentService extends Service

2.看看構(gòu)造方法

/**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
這里可以看到剛才為嘛給IntentService帶個(gè)String的參數(shù)了,原來(lái)給是工作線程取名字呀
    public IntentService(String name) {
        super();
        mName = name;
    }

3.因?yàn)槭抢^承Service的,所以我們可以看看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();
   //這里創(chuàng)建工作線程,所以使用intentService為什么不需要?jiǎng)?chuàng)建工作線程
       HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
       thread.start();
   //獲取looper,與handler產(chǎn)生聯(lián)動(dòng),實(shí)現(xiàn)消息的通信
       mServiceLooper = thread.getLooper();
       mServiceHandler = new ServiceHandler(mServiceLooper);
   }

這里小結(jié)下(IntentService里有什么東西)
1.創(chuàng)建了一個(gè)具有l(wèi)ooper的工作線程
2.創(chuàng)建了一個(gè)線程通信的Handler
3.把具有l(wèi)ooper的線程跟handler聯(lián)動(dòng)

三.IntentService具體實(shí)現(xiàn)

當(dāng)一個(gè)IntentService開(kāi)啟時(shí),先調(diào)用onCreate方法,然后會(huì)調(diào)用onStartCommand(),然后調(diào)用onStart(),儲(chǔ)存message,handler發(fā)送消息,handleMessage()處理消息,然后onHandleIntent交給子類去實(shí)現(xiàn),等message都處理完了,stopSelf(msg.arg1)停止服務(wù)

    //繼承Handler類
    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 onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId; //這里要注意,儲(chǔ)存這個(gè)startId是有用的,后面會(huì)講到
        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(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }
   @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

這里有個(gè)關(guān)鍵,每次start(),都會(huì)把message存儲(chǔ)到messagequeue隊(duì)列中,messagequeue是單線程隊(duì)列,那么intentService是怎么知道任務(wù)全部完成才會(huì)去取消任務(wù)的呢?
可以看看ActiveServices源碼
關(guān)鍵代碼

boolean stopServiceTokenLocked(ComponentName className, IBinder token,
            int startId) {
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className
                + " " + token + " startId=" + startId);
        ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
        if (r != null) {
            if (startId >= 0) {
                // Asked to only stop if done with all work.  Note that
                // to avoid leaks, we will take this as dropping all
                // start items up to and including this one.
                ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
                if (si != null) {
                    while (r.deliveredStarts.size() > 0) {
                        ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
                        cur.removeUriPermissionsLocked();
                        if (cur == si) {
                            break;
                        }
                    }
                }

                if (r.getLastStartId() != startId) {
                    return false;
                }

                if (r.deliveredStarts.size() > 0) {
                    Slog.w(TAG, "stopServiceToken startId " + startId
                            + " is last, but have " + r.deliveredStarts.size()
                            + " remaining args");
                }
            }

            synchronized (r.stats.getBatteryStats()) {
                r.stats.stopRunningLocked();
            }
            r.startRequested = false;
            if (r.tracker != null) {
                r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
                        SystemClock.uptimeMillis());
            }
            r.callStart = false;
            final long origId = Binder.clearCallingIdentity();
            bringDownServiceIfNeededLocked(r, false, false);
            Binder.restoreCallingIdentity(origId);
            return true;
        }
        return false;
    }

ActiveServices里的stopServiceTokenLocked()里的判斷r.getLastStartId()!= startId,來(lái)判斷當(dāng)前startId是不是最后一個(gè)startId,是就執(zhí)行r.stats.stopRunningLocked()來(lái)終止

課外知識(shí)
Handler是負(fù)責(zé)線程間的通信的
HandlerThread是什么呢?簡(jiǎn)單看看介紹(這個(gè)類蠻重要的 ,想要了解大家可以去查查資料,原理也不難)

/**
* Handy class for starting a new thread that has a looper. The looper can then be 
* used to create handler classes. Note that start() must still be called.
*/
是一個(gè)擁有l(wèi)ooper的線程類,這個(gè)looper可以用來(lái)跟handler來(lái)互動(dòng),但一定要用start方法來(lái)開(kāi)啟
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容