標籤:android des style blog http java
IntentService可以做什麼:
如果你有一個任務,分成n個子任務,需要它們按照順序完成。如果需要放到一個服務中完成,那麼IntentService就會使最好的選擇。
IntentService是什麼:
IntentService是一個Service(看起來像廢話,但是我第一眼看到這個名字,首先注意的是Intent啊。),所以如果自訂一個IntentService的話,一定要在AndroidManifest.xml裡面聲明。
從上面的“可以做什麼”我們大概可以猜測一下IntentService要有什麼特性。
首先要明確的是,如果在Activity中啟動一個Service,那麼這個Service是在主線程中的。所以在IntentService中需要一個背景工作執行緒來完成Intent請求。從IntentService的定義可以印證該猜測:
IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. 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.
IntentService用來按要求處理非同步請求(以Intent的方式發送的)。用戶端通過調用startService(Intent)發送請求,服務會按照要求啟動,用自己的背景工作執行緒(區別於UI主線程)處理每個Intent(請求),當完成所有的請求之後,自動關閉。
IntentService源碼解析:
乾貨來了!IntentService程式碼封裝含了一個背景工作執行緒Thread、背景工作執行緒的Looper、背景工作執行緒的Handler。背景工作執行緒用來幹活的,Looper用來讓線程運轉起來的,Handler負責向線程傳送工作內容的。IntentService的源碼簡潔透徹的體現了這一個機制。光是看看這個機制就值了。源碼如下:
路徑:alps\frameworks\base\core\java\android\app\IntentService.java
public abstract class IntentService extends Service { private volatile Looper mServiceLooper; 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) {
//自訂的IntentService子類主要就是實現onHandleIntent這個函數了。注意執行完這個之後就
//stopSelf了,傳入的參數是startId。 onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public IntentService(String name) { super(); mName = name; } /** * Sets intent redelivery preferences. Usually called from the constructor * with your preferred semantics. * * <p>If enabled is true, * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT}, so if this process dies before * {@link #onHandleIntent(Intent)} returns, the process will be restarted * and the intent redelivered. If multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. * * <p>If enabled is false (the default), * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent * dies along with it. */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate();
//好好看看下面這個代碼,啟動了一個背景工作執行緒,擷取線程的Looper,然後用這個Looper初始化Handler控制代碼
//這樣以後可以直接用mHandler.sendMessage的方式將任務直接放到背景工作執行緒了。
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(Intent intent, int startId) {
//從訊息佇列中擷取一個訊息,一般都是用這種方式初始化一個訊息,而不是用new message()形式
//效率更高,代碼更健壯 Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId;// msg.obj = intent;//這個就是startService的時候傳入的Intent了, mServiceHandler.sendMessage(msg);//將包含請求內容Intent的message傳入到背景工作執行緒中 } /** * You should not override this method for your IntentService. Instead, * override {@link #onHandleIntent}, which the system calls when the IntentService * receives a start request. * @see android.app.Service#onStartCommand */ @Override public int onStartCommand(Intent intent, int flags, int startId) {
//注意調用了onStart,和它傳入的值。 onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.quit(); } /** * Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @see android.app.Service#onBind */ @Override public IBinder onBind(Intent intent) { return null; } /** * 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 {@link #stopSelf}. * * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. */ protected abstract void onHandleIntent(Intent intent);}
從線程分析:
如果是自訂IntentService的話,可以在函數中列印Thread.currentThread().getName()將當前所線上程列印出來。就會發現,只有onHandleIntent的執行是在另外一個新線程中,其他函數(onCreate/onStart/onStartCommand等)的執行都是在main線程(主線程的名稱)中。
範例程式碼:
實際的代碼參考如下:
package com.example.fmdemo;import android.app.IntentService;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class IntentServiceDemo extends IntentService {private static final String TAG = "IntentServiceDemo";public IntentServiceDemo() {super("IntentServiceDemo");}public IntentServiceDemo(String name) {super(name);// TODO Auto-generated constructor stub}@Overrideprotected void onHandleIntent(Intent arg0) {// TODO Auto-generated method stubString action = arg0.getExtras().getString("param");if ("oper1".equals(action)) {Log.i(TAG, "onHandleIntent oper1 threadname = "+ Thread.currentThread().getName());} else if ("oper2".equals(action)) {Log.i(TAG, "onHandleIntent oper2 threadname = "+ Thread.currentThread().getName());}try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.i(TAG, "onBind threadname = " + Thread.currentThread().getName());return super.onBind(intent);}@Overridepublic void onCreate() {// TODO Auto-generated method stubLog.i(TAG, "onCreate threadname = " + Thread.currentThread().getName());super.onCreate();}@Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i(TAG, "onDestroy threadname = " + Thread.currentThread().getName());super.onDestroy();}@Overridepublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubLog.i(TAG, "onStart threadname = " + Thread.currentThread().getName());super.onStart(intent, startId);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.i(TAG, "onStartCommand threadname = "+ Thread.currentThread().getName());return super.onStartCommand(intent, flags, startId);}@Overridepublic void setIntentRedelivery(boolean enabled) {// TODO Auto-generated method stubLog.i(TAG, "setIntentRedelivery threadname = "+ Thread.currentThread().getName());super.setIntentRedelivery(enabled);}}
在自訂的Activity的onCreate中添加如下代碼:
Intent startServiceIntent = new Intent("com.example.fmdemo.intentservice");Bundle bundle = new Bundle();bundle.putString("param", "oper1");startServiceIntent.putExtras(bundle);startService(startServiceIntent);Intent startServiceIntent2 = new Intent("com.example.fmdemo.intentservice");Bundle bundle2 = new Bundle();bundle2.putString("param", "oper2");startServiceIntent2.putExtras(bundle2);startService(startServiceIntent2);
運行結果如下:
07-01 06:58:23.557: I/IntentServiceDemo(3732): onCreate threadname = main07-01 06:58:23.571: I/IntentServiceDemo(3732): onStartCommand threadname = main07-01 06:58:23.571: I/IntentServiceDemo(3732): onStart threadname = main07-01 06:58:23.576: I/IntentServiceDemo(3732): onHandleIntent oper1 threadname = IntentService[IntentServiceDemo]07-01 06:58:23.577: I/IntentServiceDemo(3732): onStartCommand threadname = main07-01 06:58:23.577: I/IntentServiceDemo(3732): onStart threadname = main07-01 06:58:25.577: I/IntentServiceDemo(3732): onHandleIntent oper2 threadname = IntentService[IntentServiceDemo]07-01 06:58:27.579: I/IntentServiceDemo(3732): onDestroy threadname = main
可以看到onHandleIntent是在不同main主線程的背景工作執行緒中啟動並執行。
IntentService使用比較簡單,但是實現機制比較有趣。感興趣的同學可以自己把代碼敲進去看看。
參考文章:
1. Android中IntentService的原理及使用
2. IntentService