如何使用IntentService

參考 https://developer.android.google.cn/reference/android/app/IntentService.html

IntentService定義

  • IntentService繼承與Service,用來處理異步請求。客戶端可以通過startService(Intent)方法傳遞請求給IntentService。IntentService在onCreate()方法中通過HandlerThread單獨(dú)開啟一個線程來依次處理所有Intent請求對象所對應(yīng)的任務(wù),這樣以免事務(wù)處理阻塞主線程(ANR)。執(zhí)行完所一個Intent請求對象所對應(yīng)的工作之后,如果沒有新的Intent請求達(dá)到,則自動停止Service;否則執(zhí)行下一個Intent請求所對應(yīng)的任務(wù)。

  • IntentService在處理事務(wù)時,還是采用的Handler方式,創(chuàng)建一個名叫ServiceHandler的內(nèi)部Handler,并把它直接綁定到HandlerThread所對應(yīng)的子線程。 ServiceHandler把處理一個intent所對應(yīng)的事務(wù)都封裝到叫做onHandleIntent的抽象方法;因此我們直接實(shí)現(xiàn)抽象方法onHandleIntent,再在里面根據(jù)Intent的不同進(jìn)行不同的事務(wù)處理就可以了。 另外,IntentService默認(rèn)實(shí)現(xiàn)了onbind()方法,返回值為null。

  • 源碼

      public abstract class IntentService extends Service {
          private volatile Looper mServiceLooper;
          private volatile ServiceHandler mServiceHandler;
          private String mName;
          private boolean mRedelivery;
          
          // 內(nèi)部Handler處理
          private final class ServiceHandler extends Handler {
              public ServiceHandler(Looper looper) {
                  super(looper);
              }
      
              @Override
              public void handleMessage(Message msg) {
                  onHandleIntent((Intent)msg.obj);
                  // 關(guān)閉當(dāng)前Service
                  stopSelf(msg.arg1);
              }
          }
      
         
          public IntentService(String name) {
              super();
              mName = name;e;     
          }
       
        
          public void setIntentRedelivery(boolean enabled) {
              mRedelivery = enabled;
          }
      
          @Override
          public void onCreate() {
              super.onCreate();
              HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
              thread.start();
      
              mServiceLooper = thread.getLooper();
              mServiceHandler = new ServiceHandler(mServiceLooper);
          }
      
          @Override
          public void onStart(@Nullable Intent intent, int startId) {
              // 發(fā)送消息(Intent)
              Message msg = mServiceHandler.obtainMessage();
              msg.arg1 = startId;
              msg.obj = intent;
              mServiceHandler.sendMessage(msg);
          }
      
          @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();
          }
      
          @Override
          @Nullable
          public IBinder onBind(Intent intent) {
              return null;
          }
    
          // 需要覆蓋該方法進(jìn)行一步處理
          @WorkerThread
          protected abstract void onHandleIntent(@Nullable Intent intent);
      }
    

實(shí)現(xiàn)方式

  • 定義一個TestIntentService繼承IntentService

      public class TestIntentService extends IntentService {
      
          // 注意構(gòu)造函數(shù)參數(shù)為空,這個字符串就是WorkThread的名字
          public TestIntentService() {
              super("TestIntentService");
          }
      
          @Override
          public void onCreate() {
              Log.d("TIS","onCreate()");
              super.onCreate();
          }
    
          @Override
          public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
              Log.d("TIS","onStartCommand()");
              return super.onStartCommand(intent, flags, startId);
          }
      
          @Override
          public void onDestroy() {
              super.onDestroy();
              Log.d("TIS","onDestroy()");
          }
      
          @Override
          protected void onHandleIntent(@Nullable Intent intent) {
              if (intent != null) {
                  int taskId = intent.getIntExtra("taskId", -1);
                  // 依次處理Intent請求
                  switch (taskId) {
                      case 0:
                          Log.d("TIS","handle task0");
                          break;
                      case 1:
                          Log.d("TIS","handle task1");
                          break;
                      case 2:
                          Log.d("TIS","handle task2");
                          break;
                  }
              }
          }
      }
    
  • Manifest.xml中注冊

      <application
          ........>
          <activity .../>
    
          <service android:name=".service.TestIntentService" />
      </application>
    
  • 啟動Service

      //同一服務(wù)只會開啟一個WorkThread,在onHandleIntent函數(shù)里依次處理Intent請求。
      Intent i0 = new Intent(this, TestIntentService.class);
      Bundle b0 = new Bundle();
      b0.putInt("taskId",0);
      i0.putExtras(b0);
      startService(i0);
    
      Intent i1 = new Intent(this, TestIntentService.class);
      Bundle b1 = new Bundle();
      b1.putInt("taskId",1);
      i1.putExtras(b1);
      startService(i1);
    
      Intent i2 = new Intent(this, TestIntentService.class);
      Bundle b2 = new Bundle();
      b2.putInt("taskId",2);
      i2.putExtras(b2);
      startService(i2);
    
      startService(i1);
      startService(i0);
    
  • 運(yùn)行結(jié)果及生命周期

      D/TIS: onCreate()
      D/TIS: onStartCommand()
      D/TIS: handle task0
      D/TIS: onStartCommand()
      D/TIS: onStartCommand()
      D/TIS: onStartCommand()
      D/TIS: handle task1
      D/TIS: onStartCommand()
      D/TIS: handle task2
      D/TIS: handle task1
      D/TIS: handle task0
      D/TIS: onDestroy()
    
  • Android Studio自動創(chuàng)建IntentService如下:

    代碼沒做,模板代碼是提供靜態(tài)方法,方便調(diào)用

      public class HelloIntentService extends IntentService {
          // TODO: Rename actions, choose action names that describe tasks that this
          // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
          private static final String ACTION_FOO = "com.cyxoder.interstudy.service.action.FOO";
          private static final String ACTION_BAZ = "com.cyxoder.interstudy.service.action.BAZ";
      
          // TODO: Rename parameters
          private static final String EXTRA_PARAM1 = "com.cyxoder.interstudy.service.extra.PARAM1";
          private static final String EXTRA_PARAM2 = "com.cyxoder.interstudy.service.extra.PARAM2";
      
          public HelloIntentService() {
              super("HelloIntentService");
          }
      
          /**
           * Starts this service to perform action Foo with the given parameters. If
           * the service is already performing a task this action will be queued.
           *
           * @see IntentService
           */
          // TODO: Customize helper method
          public static void startActionFoo(Context context, String param1, String param2) {
              Intent intent = new Intent(context, HelloIntentService.class);
              intent.setAction(ACTION_FOO);
              intent.putExtra(EXTRA_PARAM1, param1);
              intent.putExtra(EXTRA_PARAM2, param2);
              context.startService(intent);
          }
      
          /**
           * Starts this service to perform action Baz with the given parameters. If
           * the service is already performing a task this action will be queued.
           *
           * @see IntentService
           */
          // TODO: Customize helper method
          public static void startActionBaz(Context context, String param1, String param2) {
              Intent intent = new Intent(context, HelloIntentService.class);
              intent.setAction(ACTION_BAZ);
              intent.putExtra(EXTRA_PARAM1, param1);
              intent.putExtra(EXTRA_PARAM2, param2);
              context.startService(intent);
          }
      
          @Override
          protected void onHandleIntent(Intent intent) {
              if (intent != null) {
                  final String action = intent.getAction();
                  if (ACTION_FOO.equals(action)) {
                      final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                      final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                      handleActionFoo(param1, param2);
                  } else if (ACTION_BAZ.equals(action)) {
                      final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                      final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                      handleActionBaz(param1, param2);
                  }
              }
          }
      
          /**
           * Handle action Foo in the provided background thread with the provided
           * parameters.
           */
          private void handleActionFoo(String param1, String param2) {
              // TODO: Handle action Foo
              throw new UnsupportedOperationException("Not yet implemented");
          }
      
          /**
           * Handle action Baz in the provided background thread with the provided
           * parameters.
           */
          private void handleActionBaz(String param1, String param2) {
              // TODO: Handle action Baz
              throw new UnsupportedOperationException("Not yet implemented");
      }
    
  • 原理

    IntentService在onCreate()函數(shù)中通過HandlerThread單獨(dú)開啟一個線程來依次處理所有Intent請求對象所對應(yīng)的任務(wù)。通過onStartCommand()傳遞給服務(wù)intent被依次插入到工作隊列中。工作隊列又把intent逐個發(fā)送給onHandleIntent()。

注意:所有請求都是在一個單獨(dú)的工作線程上處理的——它們可能會在必要的時候(并不會阻塞應(yīng)用程序的主循環(huán)),但每次只處理一個請求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,480評論 2 379

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

  • 先貼出官方關(guān)于IntentService的解釋: IntentService is a base class fo...
    Elder閱讀 552評論 0 2
  • 一、IntentService簡介 IntentService是Service的子類,比普通的Service增加了...
    Ten_Minutes閱讀 1,636評論 2 6
  • 本篇文章是繼續(xù)上篇android圖片壓縮上傳系列-基礎(chǔ)篇文章的續(xù)篇。主要目的是:通過Service來執(zhí)行圖片壓縮任...
    laogui閱讀 4,457評論 5 62
  • 原文地址 創(chuàng)建一個后臺服務(wù): IntentService類提供一個直接的結(jié)構(gòu)對于一個單獨(dú)后臺線程執(zhí)行操作。這就允許...
    CyrusChan閱讀 1,315評論 0 4
  • 春風(fēng)化雨 難得的是,媽媽回來的較以往早; 難得的是,和媽媽心平氣和地聊起了天; 難得的是,天氣微涼,而我,...
    只一閱讀 694評論 0 0