在Android
的四大組件中,Service
排行老二,在Android
中的主要作用是后臺服務,進行與界面無關的操作。由于Service
運行在主線程,所以進行異步操作需要在子線進行。為此Android
為我們提供了IntentService
。 IntentService
是一個抽象類,繼承至Service
,主要方便我們新建工作線程進行異步操作。提交任務到IntentService
時,異步任務以串行方式進行處理,意味著工作線程一次只處理一個任務。而且當所有任務都完成之后,會自動停止Service
,不需要我們手動停止。
IntentService 的使用
- 我們定義
DownloadService
類并繼承至IntentService
。來模擬網絡下載的過程。
public class DownloadService extends IntentService {private static int count = 0;/*** 主要用于調用服務類構造器** @param name 用于區分不同任務*/public DownloadService(String name) {super(name);}/*** AndroidManifest.xml配置清單需要配置** @param*/public DownloadService() {super("action");}/***主要重寫該方法,在該方法內進行異步操作。**/@Overrideprotected void onHandleIntent(Intent intent) {Log.i("Download", "onHandleIntent" + count);count++;String name = intent.getStringExtra("action");if (name.equals("download")) {for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();return;}Log.i("Download", "download:" + count);}}}//以下方法的重寫,僅僅為了打印日志@Overridepublic void onDestroy() {super.onDestroy();Log.i("Download", "onDestroy");}@Overridepublic void onCreate() {super.onCreate();Log.i("Download", "onCreate");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);Log.i("Download", "onStart");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("Download", "onStartCommand");return super.onStartCommand(intent, flags, startId);}
}復制代碼
- 在AndroidManifest.xml配置
DownloadService
。
<service android:name=".DownloadService"/>
復制代碼
- 在MainActivity類中循環調用Service,啟動多循環任務。
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent=new Intent(this,DownloadService.class);for (int i =0;i<3;i++){intent.putExtra("action","download");intent.putExtra("count",""+i);startService(intent);}}
復制代碼
- 運行結果
分析: 從運行結果知道,IntentService
在運行多個任務情況下,只調用一次onCreate
,調用多次onStartCommand
,跟Service
的生命周期一致。但,只有在運行完download:1
之后才會去運行download:2
,接著是download:3
。最后所有任務結束后會自動調用onDestroy
,停止服務。在這里需要注意的是,和Service
并不同,Service
需要我們手動停止服務。對于結果的回調,可以采用接口回調,廣播,EventBus
。
那么,IntentService
是如何在Service
中實現異步操作和串行處理任務的呢?
IntentService內部實現
- 查看IntentService的onCreate方法
@Overridepublic void onCreate() {super.onCreate();//分析一HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();mServiceLooper = thread.getLooper();分析二mServiceHandler = new ServiceHandler(mServiceLooper);}
復制代碼
分析一
HandThread
繼承Thread
,通過start
方法創建工作線程,內部建立Looper
來達到消息循環,通過Hanlder
消息機制來達到串行的效果和處理多任務。HandThread
和Handler
消息機制,可以另外查看文章。
分析二
ServiceHandler
繼承Handler
,與普通的Handler
并沒有區別,在其內容處理handleMessage
。即調用IntentService
的onHandleIntent
;
private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}
復制代碼
- 那么,當我們在
Activity
中重復調用startService
方法時,只會多次調用onStartCommand
方法,并不會重復調用onCreate
方法。我們看看onStartComamnd
方法的實現。
@Overridepublic int onStartCommand(@Nullable Intent intent, int flags, int startId) {onStart(intent, startId);return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}
復制代碼
可以看得出,調用了onStart
方法了。而onStart方法只是將我們的Intent包裝成Message,通過Handler發送出去,并在Handler中進行處理,調用我們的onHandleIntent
。進而調用我們實現onHandleIntent
的代碼。
@Overridepublic void onStart(@Nullable Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}
復制代碼
總結
IntentService
并沒有什么的新的技術含量,在了解HandlerTread和Handler的消息機制下,對Handler+Thread+Service
作一個封裝,更適合我們后臺進行異步耗時操作的場景。有效避免通過new
多個Thread
。
知識點分享
Android消息機制
HandlerThread必知必會