Android IntentService使用介紹以及原理分析

簡介

  • 在Android應(yīng)用的程序中菊值,普通的Service中的代碼是運行在主線程中的壳猜,如果想要在Service中做些耗時的操作缰盏,就很容易出現(xiàn)ANR的現(xiàn)象(大概是20秒)祠锣,那么我們經(jīng)常的做法就是,在onStartCommon方法中開啟一個子線程然后內(nèi)部執(zhí)行耗時的操作泵三,在執(zhí)行完畢后如果需要自動停止服務(wù)需要在子線程的run方法中調(diào)用stopSelf()來停止服務(wù)耕捞。
  • 雖說在Service中執(zhí)行耗時的代碼可以很容易的實現(xiàn)衔掸,但是Android提供的IntentService類可以很方便的解決了自己開啟線程和手動停止服務(wù)的問題。接下來看看IntentService的使用步驟砸脊。

使用步驟

  • IntentService是一個抽象類內(nèi)部有一個抽象的方法 handleIntent(),繼承至Service類.所以使用它需要繼承它實現(xiàn)抽象方法具篇。
      public class MyIntentService extends IntentService {
      private static final String TAG = "MyIntentService";
      public MyIntentService() {
          super("MyIntentService");
      }
    
      @Override
      protected void onHandleIntent(Intent intent) {
          //在這里通過intent攜帶的數(shù)據(jù)纬霞,開進行任務(wù)的操作凌埂。
          Log.d(TAG, "onHandleIntent: " + Thread.currentThread().getName());
      }
    
      @Override
      public void onDestroy() {
          super.onDestroy();
          Log.d(TAG, "onDestroy: ");
        }
    }
    
  • 然后調(diào)用StartService()啟動異步后臺服務(wù)類 IntentService。
      startService.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  Intent intent = new Intent(MainActivity.this, MyIntentService.class);
                  startService(intent);
              }
          });
    

源碼分析

  • 服務(wù)啟動的過程中诗芜,會去執(zhí)行服務(wù)的生命周期方法瞳抓,在開啟服務(wù)的時候,有兩種方式伏恐,分別為startService和bindService
  • startService方式啟動孩哑,生命周期方法執(zhí)行的順序是 onCreate(),onStartCommand() onStart() onDestroy(),按照生命周期執(zhí)行順序我們查看IntentService的源碼
   // onCreate方法的分析
    @Override
   public void onCreate() {
       super.onCreate();
       HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
       //創(chuàng)建了一個Looper對象 & MessageQueue對象 調(diào)用了Looper.loop方法
       thread.start();
       //   獲取到HandlerThread中創(chuàng)建好的Looper對象翠桦。
       mServiceLooper = thread.getLooper();
       //ServiceHandler extends Handler横蜒,綁定了HandlerThread中的Looper對象 ;那個線程調(diào)用了Looper中的loop方法销凑,Handler的dispatchMessage方法就運行在那個線程中丛晌。
       mServiceHandler = new ServiceHandler(mServiceLooper);
   }
 //onStartCommand()方法分析
  public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
       // 調(diào)用了onStart方法
       onStart(intent, startId);
       return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
   }
//onStart方法
public void onStart(@Nullable Intent intent, int startId) {
       //在這里構(gòu)造了一個消息對象
       Message msg = mServiceHandler.obtainMessage();

       msg.arg1 = startId;
       //將intent 包裝到了Message的obj中,
       msg.obj = intent;
       //然后調(diào)用sendMessage()將消息插入到隊列中斗幼。
       //最終消息被取出然后被分發(fā)澎蛛,最后調(diào)用了handleMessage()來處理這個消息
       mServiceHandler.sendMessage(msg);
   }
   //ServiceHandler handleMessage方法的分析
   private final class ServiceHandler extends Handler {
       public ServiceHandler(Looper looper) {
           super(looper);
       }

       @Override
       public void handleMessage(Message msg) {
           //SeriviceHandler 的handleMessage()方法中 將接受到的消息交給onHandleIntent來處理,onHandleIntent方法就是我們實現(xiàn)的方法蜕窿,獲取到Intent谋逻,處理任務(wù)。
           onHandleIntent((Intent) msg.obj);
           //執(zhí)行完 結(jié)束服務(wù)
           stopSelf(msg.arg1);
       }
   }
  // onDestroy()方法的處理
  @Override
   public void onDestroy() {
       //將消息隊列中的所有消息給移除桐经,包括處理中的和未處理的
       mServiceLooper.quit();
   }

總結(jié)說來就是毁兆,開啟服務(wù)執(zhí)行onCreate()方法,方法中創(chuàng)建好了一個子線程(HandlerThread)阴挣,(子線程中創(chuàng)建好了一個Looper對象同時創(chuàng)建好了一個MessagqQueue消息隊列气堕,然后開啟輪詢消息隊列。)屯吊,內(nèi)部創(chuàng)建好的Handler與子線程中的Looper對象綁定送巡。onCreate只有在服務(wù)第一次創(chuàng)建的時候才會調(diào)用,之后每次調(diào)用都只會執(zhí)行onStartCommand方法盒卸,在此方法中我們構(gòu)建好了一個Message對象骗爆,并且將傳遞進來的Intent封裝在Mesage,一起發(fā)送到消息隊列中蔽介。經(jīng)過輪詢將消息分發(fā)到Handler的handleMessage中處理摘投,此時獲取到Message中攜帶的Intent傳遞給我們實現(xiàn)好的handleIntent方法中進行任務(wù)的處理煮寡,處理完畢自動調(diào)用StopSlef來結(jié)束服務(wù)。在onDestroy方法會把所有消息都給退出犀呼。

  • 上文中我們分析了startService方法啟動的服務(wù)幸撕,那bindService方式啟動服務(wù)的分析如下(綁定服務(wù),建立長期通信)外臂,bindService啟動會執(zhí)行 onCreate -> onBind -> onUnBind -> onDestroy方法坐儿。
 //onCreate方法上文中已經(jīng)分析
 //onBind()
  public IBinder onBind(Intent intent) {
       //直接返回null了。那么不對會Mesage對象和發(fā)送消息到隊列中宋光,
       //然后回調(diào)handleIntent方法了貌矿。
       return null;
   }

所以bindService方式啟動服務(wù),不會進行多線程的操作罪佳。

問題記錄

簡單描述一下IntentService
  • IntentService是一個特殊的Service類逛漫,是實現(xiàn)了多線程處理異步請求的一個服務(wù)類,在handleIntent方法中進行耗時的操作赘艳,如果有多個耗時的操作任務(wù)酌毡,會按照順序去一個一個的執(zhí)行,執(zhí)行完一個關(guān)閉一個蕾管。
在源碼handleMessage方法中為什么執(zhí)行完handleIntent方法會去調(diào)用帶參數(shù)的stopSelf()
  • 因為stopSelf()的執(zhí)行會立刻將服務(wù)停止掉枷踏,而帶參數(shù)的stopSelf(int startId)會在所有任務(wù)執(zhí)行完畢后將服務(wù)給停止。通常情況下調(diào)用stopSelf(int satrtId)方法不會立刻去執(zhí)行停止服務(wù)的操作娇掏,會去判斷最近執(zhí)行任務(wù)的次數(shù)是否和startId相等呕寝,如果相等就立刻執(zhí)行停止服務(wù)的操作。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婴梧,一起剝皮案震驚了整個濱河市下梢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌塞蹭,老刑警劉巖孽江,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異番电,居然都是意外死亡岗屏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門漱办,熙熙樓的掌柜王于貴愁眉苦臉地迎上來这刷,“玉大人,你說我怎么就攤上這事娩井∠疚荩” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵洞辣,是天一觀的道長咐刨。 經(jīng)常有香客問我昙衅,道長,這世上最難降的妖魔是什么定鸟? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任而涉,我火速辦了婚禮,結(jié)果婚禮上联予,老公的妹妹穿的比我還像新娘啼县。我一直安慰自己,他們只是感情好躯泰,可當(dāng)我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布谭羔。 她就那樣靜靜地躺著,像睡著了一般麦向。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上客叉,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天诵竭,我揣著相機與錄音,去河邊找鬼兼搏。 笑死卵慰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的佛呻。 我是一名探鬼主播裳朋,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吓著!你這毒婦竟也來了鲤嫡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤绑莺,失蹤者是張志新(化名)和其女友劉穎暖眼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纺裁,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡诫肠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了欺缘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栋豫。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谚殊,靈堂內(nèi)的尸體忽然破棺而出丧鸯,到底是詐尸還是另有隱情,我是刑警寧澤络凿,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布骡送,位于F島的核電站昂羡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏摔踱。R本人自食惡果不足惜虐先,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望派敷。 院中可真熱鬧蛹批,春花似錦、人聲如沸篮愉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽试躏。三九已至猪勇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颠蕴,已是汗流浹背泣刹。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犀被,地道東北人椅您。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像寡键,于是被迫代替她去往敵國和親掀泳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,982評論 2 361

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

  • 鬧鈴響西轩,關(guān)掉员舵,清醒一兩分鐘,起床遭商,上廁所固灵,打開聽書,綁上頭發(fā)劫流,做一套保健操巫玻,開始洗漱,慢慢往臉上擦著水乳液防曬祠汇,這...
    薇安妮閱讀 233評論 0 0
  • 第五天仍秤,目標一塔縣 今天,途經(jīng)卡拉庫里湖可很、慕士塔格峰诗力、石頭城、塔什庫爾干縣(塔縣)我抠。行程約300公里苇本,...
    燕楓簡書閱讀 496評論 0 0
  • 剛認識c先生的時候袜茧,不覺得他怎么樣,相貌平平還帶著眼鏡瓣窄,身材也不高笛厦,但我卻從他身上感覺到一種不一樣的氣息,...
    晴空蔚藍閱讀 199評論 0 1
  • 一朵花俺夕,我看到的是在暴風(fēng)中掙扎后的綻放裳凸; 一顆水晶,我看到的是渾濁世界背后的眼睛劝贸; 一只小鳥姨谷,我...
    烽火煤閱讀 248評論 0 0
  • 晚上爸爸下班回家了,坐在椅子上映九,一邊休息梦湘,一邊看報紙,我看見爸爸很累的樣子氯迂,連忙倒了一杯水践叠,說:爸爸喝口水吧,爸爸...
    敏敏_98f5閱讀 85評論 0 0