【轉載】Android IntentService使用全面介紹及源碼解析

一 IntentService介紹

IntentService定義的三個基本點:是什麼?怎麼用?如何work?

官方解釋以下:java

//IntentService定義的三個基本點:是什麼?怎麼用?如何work?*/android

一、IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand.express

二、Clients send requests through 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.app

//解釋了IntentService的好處,以及How to use IntentService*/dom

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 onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.異步

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.async

總結IntentService的特色以下:

一、IntentService是Service類的子類,用來處理異步請求。ide

二、客戶端能夠經過startService(Intent)方法傳遞請求給IntentService函數

三、IntentService在onCreate()函數中經過HandlerThread單獨開啓一個線程來處理全部Intent請求對象(經過startService的方式發送過來的)所對應的任務,這樣以避免事務處理阻塞主線程。

四、執行完所一個Intent請求對象所對應的工做以後,若是沒有新的Intent請求達到,則自動中止Service;不然執行下一個Intent請求所對應的任務。

五、IntentService在處理事務時,仍是採用的Handler方式,建立一個名叫ServiceHandler的內部Handler,並把它直接綁定到HandlerThread所對應的子線程。 ServiceHandler把處理一個intent所對應的事務都封裝到叫作onHandleIntent的虛函數;所以咱們直接實現虛函數onHandleIntent,再在裏面根據Intent的不一樣進行不一樣的事務處理就能夠了。

IntentService最重要的一個方法onHandleIntent:

This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().

一、該函數用於針對Intent的不一樣進行不一樣的事務處理.執行完所一個Intent請求對象所對應的工做以後,若是沒有新的Intent請求達到,
則自動中止Service;不然ServiceHandler會取得下一個Intent請求傳人該函數來處理其所對應的任務。

二、全部請求都在一個單線程中,不會阻塞應用程序的主線程(UI Thread),可是同一時間只處理一個請求。

IntentService的特色、優勢、缺點?

IntentService的特色:

  1. IntentService是藉助於消息隊列實現的,因此任務的執行順序就是一個queue的形式;
  2. 因爲是單線程(一個工做線程),因此全部的任務須要排隊執行;/
  3. 避免了咱們再去建立線程和管理service的結束工做;

基於以上,IntentService與Service比較的好處有:

  • 第一,使用方便,代碼簡潔,再也不須要咱們本身像Service裏面還要去手動建立線程;
  • 第二,當操做完成時,咱們不用手動中止Service。

固然,IntentService的缺點也是顯而易見:

因爲是單個的worker thread,因此任務須要排隊,不適合大多數的多任務狀況;

二 DEMO實踐

DEMO場景描述:

主要由MainActivity和MyIntentService構成,在MainActivity中啓動服務,並傳遞兩個參數a和b,在MyIntentService中獲取參數,求和,並經過發送廣播的形式向UI返回結果,而後MainActivity在接收到廣播以後更新UI。

MainActivity.java主要作了三件事:

  1. 註冊/註銷廣播接收器;
  2. 建立UI和更新UI;
  3. 傳遞參數,啓動MyIntentService;

代碼以下:

public class MainActivity extends AppCompatActivity { private LinearLayout ll_container; private BroadcastReceiver forSumReceiver=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i("TAG","onReceive ()"); if(intent.getAction()==Constans.ACTION_RESULT){ int a=intent.getIntExtra(Constans.A,0); int result=intent.getIntExtra(Constans.RESULT,0); Log.i("TAG","onReceive --result:"+result); handleResult(a,result); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ll_container= (LinearLayout)findViewById(R.id.ll_container); Log.i("TEST","MainActivity:"+android.os.Process.myTid()); registerBroadcast(); } private void handleResult(int a,int result){ TextView textView=(TextView)ll_container.findViewWithTag(a); String old=textView.getText().toString(); String newText=old.replaceAll(" 正在計算中...",String.valueOf(result)+" 計算Success"); textView.setText(newText); } private void registerBroadcast(){ IntentFilter intentFilter=new IntentFilter(); intentFilter.addAction(Constans.ACTION_RESULT); registerReceiver(forSumReceiver,intentFilter); } private int a=1; public void addTask(View view){ int b=new Random().nextInt(101)+1; MyIntentService.startMyIntentService(this,a,b); TextView textView=new TextView(this); textView.setText(a+"+"+b+"= "+ " 正在計算中..."); textView.setTag(a); ll_container.addView(textView); a++; } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(forSumReceiver); } }

MyIntentService用於接收參數,並返回計算的結果:

public class MyIntentService extends IntentService { public MyIntentService() { //必須實現父類的構造方法 super("MyIntentService"); } @Override public void onCreate() { Log.i("TEST","onCreate()"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.i("TEST","onStart()"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("TEST","onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.i("TEST", "onBind()"); return super.onBind(intent); } @Override public void onDestroy() { Log.i("TEST","onDestroy()"); super.onDestroy(); } @Override protected void onHandleIntent(Intent intent) { Log.i("TEST","onHandleIntent():"+android.os.Process.myTid()); if (intent!=null){ String action=intent.getAction(); if(Constans.ACTION_FOR_SUM.equals(action)){ int a=intent.getIntExtra(Constans.A,0); int b=intent.getIntExtra(Constans.B,0); int result=a+b; Log.i("TEST","result: "+result); handleResult(a,result); } } } private void handleResult(int a,int result){ try{ //模擬計算耗時 Thread.sleep(3000); Intent intent=new Intent(Constans.ACTION_RESULT); intent.putExtra(Constans.RESULT,result); intent.putExtra(Constans.A,a); sendBroadcast(intent); }catch (InterruptedException e){ e.printStackTrace();; } } public static void startMyIntentService(Context context,int a,int b){ Intent intent=new Intent(context,MyIntentService.class); intent.setAction(Constans.ACTION_FOR_SUM); intent.putExtra(Constans.A,a); intent.putExtra(Constans.B,b); context.startService(intent); } }

IntentService生命週期方法執行順序以下:

07-08 10:18:51.579 com.troy.intentservicedemo I/TEST: MainActivity:30060 
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onCreate()
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStartCommand()
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStart()
07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: onHandleIntent():30223
07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: result: 23
07-08 10:19:29.100 com.troy.intentservicedemo I/TEST: onDestroy()
07-08 10:19:31.839 com.troy.intentservicedemo I/TEST: onCreate()
07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStartCommand()
07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStart()
07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: onHandleIntent():30305
07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: result: 52
07-08 10:19:34.899 com.troy.intentservicedemo I/TEST: onDestroy()

從上面Log中能夠看出:

  1. UI線程的線程ID=30060,而onHandleIntent()的線程ID分別是30223,30305;由此知道onHandleIntent()方法是執行在工做線程中的;
  2. 而且IntentService的全部請求若是是在一個生命週期中完成的話,則全部請求是在一個工做線程中順序執行的。不然,是在不一樣的工做線程中完成。
  3. 同時驗證了:執行完所一個Intent請求對象所對應的工做以後,若是沒有新的Intent請求達到,則自動中止Service;

運行效果如圖:

這裏寫圖片描述

三 IntentService源碼簡單解析

IntentService是Service的子類,擁有Service的全部生命週期方法;同時還有本身的ServiceHandler;

ServiceHandler相關源碼以下:

public abstract class IntentService extends Service { private volatile Looper mServiceLooper;//volatile關鍵字保證同步,保證可見性 private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; 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); } } public IntentService(String name) {//構造方法 super(); mName = name; }

IntentService 其實是Looper,Handler,Service 的集合體,他不只有服務的功能,還有處理和循環消息的功能。

onCreate()的源碼:建立了一個HandlerThread

@Override 
        public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }

IntentService建立時就會建立Handler線程(HandlerThread)而且啓動,而後再獲得當前線程的Looper對象來初始化IntentService的mServiceLooper,接着建立mServicehandler對象。

下面是onStart()的源碼: 調用mServiceHandler

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

當你啓動IntentService的時候,就會產生一條附帶startId和Intent的 Message併發送到MessageQueue中,接下來Looper發現MessageQueue中有Message的時候,就會中止Handler 處理消息。

handleMessage處理的代碼以下:

@Override 
        public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); }

接着調用 onHandleIntent((Intent)msg.obj),這是一個抽象的方法,其實就是咱們要重寫實現的方法,咱們能夠在這個方法裏面處理咱們的工做.當任務完成時就會調用stopSelf(msg.arg1)這個方法來結束指定的工做。

stopSelf(msg.arg1):

注意下:回調完成後回調用 stopSelf(msg.arg1),注意這個msg.arg1是個int值,至關於一個請求的惟一標識。每發送一個請求,會生成一個惟一的標識,而後將請求放入隊列,當所有執行完成(最後一個請求也就至關於getLastStartId == startId),或者當前發送的標識是最近發出的那一個(getLastStartId == startId),則會銷燬咱們的Service.若是傳入的是-1則直接銷燬。

當全部的工做執行完後:就會執行onDestroy方法。

onDestroy源碼以下:

@Override 
        public void onDestroy() { mServiceLooper.quit(); }

服務結束後調用這個方法 mServiceLooper.quit()使looper停下來。

最後總結一下上述的分析:

一、 IntentService是一個基於消息的服務,每次啓動該服務並非立刻處理你的工做,而是首先會建立對應的Looper,Handler而且在MessageQueue中添 加的附帶客戶Intent的Message對象, 當Looper發現有Message的時候接着獲得Intent對象經過在 onHandleIntent((Intent)msg.obj)中調用你的處理程序. 處理完後即會中止本身的服務. 意思是Intent的生命週期跟你的 處理的任務是一致的. 因此這個類用下載任務中很是好,下載任務結束後服務自身就會結束退出。

二、IntentService是不適合用於bindService()這樣的啓動方式的。其次咱們經過startService屢次啓動Service時,至關於在MessageQueue中添加了多個任務,就能夠實現多任務按照順序執行。

三、只有在onHandleIntent()方法中執行的代碼纔是在工做線程中運行的。IntentService的中止不是由於在handleMessage() 中執行了stopSelf(msg.arg1);而是系統本身中止的。

相關文章
相關標籤/搜索