代碼分析:IntentService詳解

Android開發(fā)中胚鸯,經(jīng)常會遇到耗時操作谬墙,比如下載文件吵聪,這個時候大家第一個想法就是交給Service去處理劲装,而Service并不能夠直接去處理耗時請求胧沫,所以我們都會在Service中開啟子線程去做這些事情昌简。那么在這個過程我們需要處理好2個問題。
1.在需要添加任務(wù)的時候就在Service中開啟線程并且執(zhí)行任務(wù)绒怨。
2.在任務(wù)結(jié)束之后關(guān)閉Service纯赎。
而IntentService將這2個問題處理得很好了。
在IntentService中南蹂,有一個私有內(nèi)部Handler的實現(xiàn)犬金。

private volatile ServiceHandler mServiceHandler;
...    
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);
        }
    }

mServiceHandler用來向內(nèi)部的HandlerThread發(fā)送需要執(zhí)行的任務(wù)。
首先六剥,在Service創(chuàng)建的時候晚顷,會啟動一個HandlerThread線程來執(zhí)行任務(wù),并且使用HandlerThread的Looper實例化mServiceHandler疗疟。

    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);
    }

然后就可以通過mServiceHandler來向HandlerThread推送需要執(zhí)行的任務(wù)该默。

    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

而onHandleIntent(@Nullable Intent intent)方法就是我們執(zhí)行具體耗時操作的地方了,通過將intent消息體傳遞進(jìn)來策彤,解析消息之后再進(jìn)行具體的耗時操作栓袖。
在ServiceHandler中的handleMessage方法中,使用stopSelf(msg.arg1)來停止線程店诗。也就是在我們耗時任務(wù)執(zhí)行完成之后裹刮,再去停止線程。
這樣很好的解決了上面的2個問題了庞瘸,而且在停止線程的時候使用stopSelf(msg.arg1)捧弃,這樣能夠規(guī)避一個新的問題。
當(dāng)Service要同時處理多個請求擦囊,你就不能在當(dāng)前一個請求處理完成之后立刻停止Service违霞,因為很可能現(xiàn)在你已經(jīng)收到了一個新的啟動Service請求(如果立刻停止,那么新來的請求就會跟著終止)霜第。
stopSelf(int)可以保證Service當(dāng)前停止的請求是基于上一個請求的葛家,因為當(dāng)我們每次startService之后户辞,Service都會有一個新的startID泌类,而通過上面的代碼我們可以找到msg.arg1就是這個startID。

    public void onStart(@Nullable Intent intent, int startId) {
        ...
        msg.arg1 = startId;
        ...
    }

那么當(dāng)stopSelf要停止的Service的startID和當(dāng)前IntentService的startID是不相同的底燎,這個時候是無法殺死Service的刃榨,這樣就能保證Service在處理多個請求的時候存活了。
另外双仍,IntentService是屬于non-sticky服務(wù)的枢希,也就是說它會在任務(wù)完成之后自己停止,所以它并不適合那種需要一直生存在后臺的Servie朱沃。
IntentService管理自啟是當(dāng)Service設(shè)置為重要時苞轿,那么他會一直運行到?jīng)]有任務(wù)了才會自己關(guān)閉茅诱,也就是說當(dāng)系統(tǒng)殺掉IntentService之后,它會自動啟動搬卒,并且把對應(yīng)的Intent傳遞進(jìn)來瑟俭,而當(dāng)沒有設(shè)置重要度的時候,也就是默認(rèn)不重要的時候契邀,當(dāng)被系統(tǒng)殺掉之后摆寄,就不會再自動啟動了。

    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

-START_REDELIVER_INTENT:在運行onStartCommand后service進(jìn)程被kill后坯门,并且沒有新的intent傳遞給它微饥。Service將移出開始狀態(tài),并且直到新的明顯的方法(startService)調(diào)用才重新創(chuàng)建古戴。因為如果沒有傳遞任何未決定的intent那么service是不會啟動欠橘,也就是期間onstartCommand不會接收到任何null的intent。

-START_NOT_STICKY:在運行onStartCommand后service進(jìn)程被kill后现恼,系統(tǒng)將會再次啟動service简软,并傳入最后一個intent給onstartCommand。直到調(diào)用stopSelf(int)才停止傳遞intent述暂。如果在被kill后還有未處理好的intent痹升,那被kill后服務(wù)還是會自動啟動。因此onstartCommand不會接收到任何null的intent畦韭。

mRedelivery可以通過set方法進(jìn)行設(shè)置疼蛾。

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市艺配,隨后出現(xiàn)的幾起案子察郁,更是在濱河造成了極大的恐慌,老刑警劉巖转唉,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皮钠,死亡現(xiàn)場離奇詭異,居然都是意外死亡赠法,警方通過查閱死者的電腦和手機(jī)麦轰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砖织,“玉大人款侵,你說我怎么就攤上這事〔啻浚” “怎么了新锈?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眶熬。 經(jīng)常有香客問我妹笆,道長块请,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任拳缠,我火速辦了婚禮负乡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘脊凰。我一直安慰自己抖棘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布狸涌。 她就那樣靜靜地躺著切省,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帕胆。 梳的紋絲不亂的頭發(fā)上朝捆,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音懒豹,去河邊找鬼芙盘。 笑死,一個胖子當(dāng)著我的面吹牛脸秽,可吹牛的內(nèi)容都是我干的儒老。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼记餐,長吁一口氣:“原來是場噩夢啊……” “哼驮樊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起片酝,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤囚衔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雕沿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體练湿,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年审轮,在試婚紗的時候發(fā)現(xiàn)自己被綠了肥哎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡断国,死狀恐怖贤姆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情稳衬,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布坐漏,位于F島的核電站薄疚,受9級特大地震影響碧信,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜街夭,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一砰碴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧板丽,春花似錦呈枉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砚殿,卻和暖如春啃憎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背似炎。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工辛萍, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羡藐。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓贩毕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仆嗦。 傳聞我的和親對象是個殘疾皇子耳幢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前言:本文所寫的是博主的個人見解,如有錯誤或者不恰當(dāng)之處欧啤,歡迎私信博主睛藻,加以改正!原文鏈接邢隧,demo鏈接 Serv...
    PassersHowe閱讀 1,408評論 0 5
  • Android中的線程 線程店印,在Android中是非常重要的,主線程處理UI界面倒慧,子線程處理耗時操作按摘。如果在主線程...
    shenhuniurou閱讀 750評論 0 3
  • [文章內(nèi)容來自Developers] Service是一個可以在后臺執(zhí)行長時間運行操作而不提供用戶界面的應(yīng)用組件。...
    岳小川閱讀 860評論 0 7
  • 農(nóng)歷八月初八 星期日 陰天陣雨 1纫谅,昨天把自己一直煩惱的事情炫贤,想通了之后,十分輕松和堅定付秕。上午看盤兰珍,又回到當(dāng)初的狀...
    畢缽羅子閱讀 158評論 1 1
  • 文:謝欣美 當(dāng)我看到《當(dāng)我們一起走過》這篇推送時,我心里想的是蘇打綠的另一首同名歌曲询吴,然而打開看卻是《我最親愛的》...
    梁可愛閱讀 270評論 3 1