Android進階知識:IntentService相關

1.前言

Android基礎知識:多線程基礎總結中除了AsyncTaskHandlerThread還提到了Android提供的另一種進行異步任務的方式IntentService。這一篇就來看看IntentService的使用和運行原理。android

2.IntentService的使用

IntentService的使用步驟分爲如下幾步:bash

1.繼承實現IntentService抽象類,複寫onHandleIntent方法多線程

public class MyIntentService extends IntentService {
    private static final String TAG = "MyIntentService";
    private int percent;
    public MyIntentService() {
        super("MyIntentServiceThread");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String type = intent.getStringExtra("type");
        switch (type) {
            case "type1":
            {
                for (percent = 0; percent <= 100; percent += 10) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, Thread.currentThread().getName() + " type1 " + percent + "% progress");

                }
                Log.d(TAG, Thread.currentThread().getName() + ":finish");
            }
            break;
        }
    }
}
複製代碼

2.在AndroidManifest.xml註冊Serviceapp

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.thread.intentservice">
    <application
        .......
        <service android:name=".MyIntentService" />
    </application>

</manifest>
複製代碼

3.啓動IntentService服務異步

Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra("type", "type1");
startService(intent);
複製代碼

運行結果: ide

3.IntentService運行原理

從使用方法上來看IntentService與通常的Service使用步驟也沒啥區別,都是先建立實現一個Service再到AndroidManifest.xml中註冊,最後啓動服務便可。那麼仍是從源碼看看IntentService到底有什麼特別的地方。函數

public abstract class IntentService extends Service {
    .......
    /**
     * 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; } 複製代碼

首先看到IntentService是個抽象類,而且繼承自Service,它的構造函數中只傳入了name,從註釋看出就是工做線程的name。既然是個Service接着就看它生命週期中的onCreate方法。oop

@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();
        // 建立HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        // 調用HandlerThread的start方法開啓線程
        thread.start();
        // 得到HandlerThread中的Looper
        mServiceLooper = thread.getLooper();
        // 建立Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
複製代碼

onCreate方法中的代碼看着有些熟悉就是以前在Android進階知識:HandlerThread相關中提到的HandlerThread的使用步驟。因此說在onCreate方法中就是建立了一個HandlerThread的工做線程,調用了它的start方法而且建立了對應Handler。先來看一下這個ServiceHandler類的實現。post

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);
        }
    }
複製代碼

ServiceHandlerIntentService的內部類,其實現也很簡單,接收了傳入的Looper後複寫handleMessage方法,handleMessage方法中收到消息後先調用了onHandleIntent方法將intent傳入。onHandleIntent方法是咱們本身實現IntentService時複寫的方法,源碼這裏是個抽象方法,主要進行異步耗時任務,而後調用stopSelf將自身關閉。ui

protected abstract void onHandleIntent(@Nullable Intent intent);
複製代碼

接着繼續按生命週期走到了onStartCommand方法。

@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 onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    
複製代碼

onStartCommand方法中又調用了onStart方法,而onStart方法建立了消息,而且將接收到的intent做爲消息的objstartId傳遞給消息arg1,最後調用mServiceHandler.sendMessage將消息發送出去。到此整個IntentService的運行流程就差很少了,最後在調用stopSelf方法後服務會調用生命週期中的onDestory方法,在IntentServiceonDestory方法中會直接調用mServiceLooper.quit()方法將Lopper退出。

另外IntentService中還有個mRedelivery成員變量能夠經過setIntentRedelivery方法設置,用來決定onStartCommand方法的返回值,從而決定服務在被異常殺死後是否自動重啓該服務。

// 布爾值變量
private boolean mRedelivery;
// setIntentRedelivery方法
public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
}
// onStartCommand返回值
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
複製代碼

4.總結

從上面的閱讀的源碼能夠知道IntentService實現異步任務是基於HandlerThread實現的。

IntentService的運行流程: 啓動服務後會先進行生命週期的onCreate方法,方法中建立HandlerThreadServiceHandler,接着進入生命週期的onStartCommand方法,onStartCommand方法中調用onStart方法,onStart方法使用ServiceHandler發送消息,handleMessage方法中接收到消息,調用複寫的onHandleIntent方法,最後調用stopSelf方法關閉本身。

IntentService與普通Service對比:

普通Service IntentService
運行在主線程 運行在建立的工做線程
須要手動調用stopService關閉 自動調用stopSelf關閉
相關文章
相關標籤/搜索