并發(fā)編程(7)Intentservice源碼分析

概述

前面分析了HandlerThread源碼赊淑,下面按照順序分析IntentService的源碼,IntentService是自己維護了一個線程钾挟,來執(zhí)行耗時的操作掺出,然后里面封裝了HandlerThread,能夠方便在子線程創(chuàng)建Handler双抽。

正文

注釋

IntentService is a base class for {@link Service}s that handle asynchronous
requests (expressed as {@link Intent}s) on demand.  Clients send requests
through {@link android.content.Context#startService(Intent)} calls; the
service is started as needed, handles each Intent in turn using a worker
thread, and stops itself when it runs out of work.

IntentService是繼承自Service用來處理異步請求的一個基類闲礼,客戶端startService發(fā)送請求,IntentService就被啟動,然后會在一個工作線程中處理傳遞過來的Intent聂抢,當任務(wù)結(jié)束后就會自動停止服務(wù)棠众。

This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread.  The IntentService class exists to
simplify this pattern and take care of the mechanics.  To use it, extend
IntentService and implement {@link #onHandleIntent(Intent)}.  IntentService
will receive the Intents, launch a worker thread, and stop the service as appropriate

工作器處理模式通常用來加載應(yīng)用主線程的耗時任務(wù),IntentService用來簡化這種模式并且專注于耗時任務(wù)的處理空盼。使用IntentService揽趾,需要繼承IntentService并且復(fù)寫onHandleIntent方法。IntentService在接收到一系列Intent之后篱瞎,啟動一個子線程痒芝,然后合適的實際關(guān)閉Service。

All requests are handled on a single worker thread -- they may take as
  long as necessary (and will not block the application's main loop), but
  only one request will be processed at a time.

所有的請求都是都是在同一個子線程中進行處理的—他們可能會花費很長時間(并不會阻塞應(yīng)用的loop線程)澄者,但是在同一時刻IntentService只能處理一個請求粱挡。

通過注釋俄精,已經(jīng)將IntentService的使用方式嘀倒,使用場景描述地相當清楚局冰,不再多解釋康二,相比較我們自己在Intent中開啟線程處理耗時任務(wù)勇蝙,IntentService不需要我們自己去關(guān)閉Service,它自己會在任務(wù)完成之后自行關(guān)閉产雹,不過每次只能處理一個任務(wù)翁锡,所以不適用于高并發(fā)馆衔,適用于請求數(shù)較少的情況,類似于APP的版本檢測更新拷获,后臺定位功能以及讀取少量的IO操作匆瓜。

成員變量

    private volatile Looper mServiceLooper;//子線程中的Looper
    private volatile ServiceHandler mServiceHandler;//內(nèi)部持有的一個Handler
    private String mName;//內(nèi)部創(chuàng)建的線程名字
    private boolean mRedelivery;//服務(wù)被異常終止后重新創(chuàng)建調(diào)用onStartCommand是否回傳Intent

ServiceHandler

  private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
          //子線程中回調(diào)Intent
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

內(nèi)部創(chuàng)建了一個ServiceHandler陕壹,然后將傳遞過來的Intent封裝成一個Message糠馆,然后再將Message封裝成一個Intent怎憋,回調(diào)onHandleIntent,其實轉(zhuǎn)換的目的就是講主線程的Intent切換到子線程中去執(zhí)行了而已毕匀。

構(gòu)造方法

  //工作線程的名字
  public IntentService(String name) {
        super();
        mName = name;
    }

onCreate

    @Override
    public void onCreate() {
        super.onCreate();
        //創(chuàng)建HandlerThread   
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        //開啟線程創(chuàng)建子線程Looper
        thread.start();
        //獲取子線程Looper
        mServiceLooper = thread.getLooper();
       //創(chuàng)建子線程Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onStartCommand

  @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        //調(diào)用onStart方法
        onStart(intent, startId);
       //根據(jù)mRedelivery的值來確定返回重傳Intent的黏性廣播還是非黏性廣播
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

onStart

  @Override
    public void onStart(@Nullable Intent intent, int startId) {
        //創(chuàng)建一個Message
        Message msg = mServiceHandler.obtainMessage();
        //消息標志皂岔,作為當前Service的標志
        msg.arg1 = startId;
        //攜帶Intent
        msg.obj = intent;
        //發(fā)送消息躁垛,此時將線程切換到子線程
        mServiceHandler.sendMessage(msg);
    }


   @Override
        public void handleMessage(Message msg) {
            //處理發(fā)送過來的消息,在子線程
            onHandleIntent((Intent)msg.obj);
           //處理完消息之后停止Service
            stopSelf(msg.arg1);
        }

onDestroy

    @Override
    public void onDestroy() {
       //退出Looper
        mServiceLooper.quit();
    }

使用方式

IntentService intentService = new IntentService("main") {
    @Override
    protected void onHandleIntent(Intent intent) {
        // 處理耗時操作
    }
};
//不需要關(guān)注Service的生命周期,IntentService會自行處理

總結(jié)

IntentService實際上內(nèi)部實例化了一個HandlerThread,并且封裝了一個Handler逊谋,所以他的工作流程通過上面的源碼胶滋,分析如下:

  1. 創(chuàng)建一個HandlerThread,開啟HandlerThread來創(chuàng)建Looper
  2. 創(chuàng)建一個Handler,傳入Looper,從而在子線程實例化Handler
  3. 在onStartCommand中獲取到的Intent作為消息的obj發(fā)送出去
  4. 然后在onHandleIntent中處理這個消息究恤,注意此時是在子線程
  5. 跟HandlerThread一樣,IntentService內(nèi)部是采用Handler來實現(xiàn)的部宿,所以任務(wù)是串行執(zhí)行的窟赏,不適用于大量耗時操作箱季。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棍掐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子作煌,更是在濱河造成了極大的恐慌,老刑警劉巖奏寨,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鹰服,居然都是意外死亡病瞳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門悲酷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來套菜,“玉大人,你說我怎么就攤上這事设易《翰瘢” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵顿肺,是天一觀的道長戏溺。 經(jīng)常有香客問我渣蜗,道長,這世上最難降的妖魔是什么于购? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任袍睡,我火速辦了婚禮斑胜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凭戴。我一直安慰自己,他們只是感情好档痪,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布乐纸。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪久窟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音,去河邊找鬼颊糜。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岁经,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼怀读,長吁一口氣:“原來是場噩夢啊……” “哼叁丧!你這毒婦竟也來了拥娄?” 一聲冷哼從身側(cè)響起牡昆,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤掸刊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后苍柏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楼咳,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡碟贾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年朱巨,在試婚紗的時候發(fā)現(xiàn)自己被綠了必峰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凭需。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出设捐,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站县袱,受9級特大地震影響显拳,放射性物質(zhì)發(fā)生泄漏杂数。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诉探,春花似錦敬肚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炒事。三九已至权薯,卻和暖如春姑躲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盟蚣。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工黍析, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屎开。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓橄仍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牍戚。 傳聞我的和親對象是個殘疾皇子侮繁,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348