handlerthread和intentservice源碼解析

在開發過程當中咱們可使用HandlerThread建立隊列,經過發送消息讓線程處理任務,重複利用線程節省系統資源開銷。能夠是使用IntentService來解決Service中不能處理耗時操做的問題。本篇文章主要從基本使用和核心源碼分析,兩個方面來介紹HandlerThread和IntentService。android

目錄

HandlerThread:

  1. HandlerThread的基本使用
  2. HandlerThread是如何和Handler關聯的?
  3. HandlerThread是如何建立Looper的?

IntentService

  1. IntentService基本使用
  2. IntentService是如何和HandlerThread和Handler關聯?
  3. Intentservice是如何發送消息的?
  4. Intentservice是如何在子線程中執行任務的?

下面爲一張流程圖,在文章的HandlerThread和IntentService的源碼分析過程當中能夠參考這張圖。bash

IntentService執行流程圖

HandlerThread介紹和源碼分析

HandlerThread是Android自帶的一個輕量級的異步處理的類,該類繼承Thread具備Thread和Handler的特性。異步

注:HandlerThread的執行流程能夠參考文章開始圖片右上角部分。ide

1. HandlerThread的基本和使用

建立Handler.Callback函數

private Handler.Callback mHandlerCallback = new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case 123:
                Log.i(TAG, (String) msg.obj + "【線程名爲】:" +
                        mHandler.getLooper().getThread().getName());
                break;
        }
        return false;
    }
};
複製代碼

建立Hanlder和HandlerThreadoop

private Handler mHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mHandlerThread = new HandlerThread("建立HandlerThread線程");
    mHandlerThread.start();
    //使用Callback和子線程的Looper建立Handler
    mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
}
複製代碼

發送消息源碼分析

switch (v.getId()) {
    case R.id.mBnt_handlerThread:
        //發送消息
        Message message = mHandler.obtainMessage(123, "這是HandlerThread發送的消息");
        message.sendToTarget();
        break;
}
複製代碼

執行結果:性能

I/MainActivity: 這是HandlerThread發送的消息【線程名爲】:建立HandlerThread線程
複製代碼

結束:ui

protected void onDestroy() {
    super.onDestroy();
    //馬上清楚
    mHandlerThread.quit();
    //消息隊列執行完以後再清除
    mHandlerThread.quitSafely();
}
複製代碼

2. IntentService是如何和HandlerThread和Handler關聯?

咱們從上面的基本使用建立Hanlder的時候應該能夠看出,Hanlder的建立使用了HanlderThread的Looper。咱們知道一個線程中只能有一個Looper,咱們平時使用Handler發送消息使用的是主線程的Looper,所以消息是在主線程中執行的。可是咱們經過下面這種指定子線程Looper的來建立Handler,那麼消息將會在子線程中執行:this

mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
複製代碼

3. HandlerThread是如何建立Looper的?

HandlerThread的Looper建立是在run()方法中建立的,它會先調用Looper.prepare()來建立Looper,將建立好的Looper賦值給mLooper這個成員變量咱們會在IntentService的時候看到它。而後會設置線程的優先級,最後是調用Looper.loop()開啓循環。下面爲建立代碼:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}
複製代碼

從上面的代碼中讀者可能發如今線程優先級設置完成後,緊接着就調用onLooperPrepared()函數。那麼這個函數又是幹嗎的呢?其實這個函數是一個空實現函數,開發人員能夠根據本身的須要來實現,能夠在裏面作一些初始化的操做等。

protected void onLooperPrepared() {}
複製代碼

其實HandlerThread最核心的就是run()方法看完上面的內容,基本是上就明白HandlerThread的執行過程。當咱們在銷燬的時候能夠經過它的quit()quitSafely()方法,這兩個方法內部調用的是Looper的方法:

//清除所有消息
public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}
//清除延遲消息,不是延遲消息將會繼續執行.
//直到隊列中沒有了消息,Looper纔會被銷燬.
public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quitSafely();
        return true;
    }
    return false;
}
複製代碼

IntentService介紹和源碼分析

IntentService繼承Service,因此它本質上是一個Service。不一樣的是它在本身內部能夠經過HandlerThread,Handler來執行耗時操做。

注:IntentService的執行流程能夠參考文章一開始的圖片

1. IntentService基本使用

IntentService的使用也很簡單,先建立IntentService子類,而且實現onHandleIntent()方法

public class MyIntentService extends IntentService {
    private final String TAG = "MyIntentService";

    /**
     * 注意將自動生成的有參書構造改爲無參構造
     * super()中必須填入線程的名字
     */
    public MyIntentService() {
        super("IntentService線程");
    }
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String extra = intent.getStringExtra("MyIntentService");
        Log.i(TAG, "傳入的內容爲:" + extra + "【線程名爲】:" + Thread.currentThread().getName());
    }
}
複製代碼

配置AndroidManifest.xml

<service android:name=".MyIntentService"/>
複製代碼

在Activity中調用

case R.id.mBnt_intentService:
    Intent intentService = new Intent(MainActivity.this,
            MyIntentService.class);
    intentService.putExtra("MyIntentService", "數據123");
    //啓動intentservice
    startService(intentService);
break;
複製代碼

2. IntentService是如何和Handler關聯?

IntentServiceonCreat()方法分別建立了HandlerThread和ServiceHandler兩個對象,HandlerThread對象咱們上面內容介紹過,讀者若是不清楚能夠返回去看看;而ServiceHandler對象是一個繼承Handler的類,這個類會在後面介紹到,咱們先暫時知道建立該函數須要指定Looper就能夠了。從下面的源碼中咱們很容易明白,thread在開啓線程後,IntentService又獲取了HandlerThread的Looper並用它來建立了Hanlder從而把IntentService、HanlderThread和Handler關聯起來了。

注:IntentService本質上是一個service,所以同一個Intentservice只會建立一次,即它的onCreate()只會調用一次;不過它的onStartCommand()和onStart()會調用屢次。

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

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}
複製代碼

3. Intentservice是如何發送消息的?

當咱們經過startService()啓動IntentService的時候它會執行:

onCreate()-->onStartCommand()-->onStart()
複製代碼

其中onStart()方法會發送消息通知Handler執行任務。

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

從上面的代碼咱們能夠知道,onStart()中將咱們在Activity傳入的intent和startId包裝到Message中並將它發送給Handler。

4. Intentservice是如何在子線程中執行任務的?

上面咱們在onCreate()方法中提到過ServiceHandler這個類繼承Handler,它也是消息的處理類。任務執行會在該類的handleMessage()方法中調用onHandleIntent()方法來異步執行。下面爲ServiceHandler的源碼:

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

咱們在onClick的方法中建立該類對象的時候傳入了HandlerThread對象的Looper,所以消息的執行是在子線程執行。handleMessage()方法將Message的Intent取出後又交給了onHandleIntent()方法處理,該方法是一個抽象函數須要開發者根據業務本身實現。當onHandleIntent()任務執行完後就會調用stopSelf()關閉服務。

總結

在開發過程當中可以合理的使用HanlderThread和IntentService可以有效程序的性能。須要注意的是HandlerThread由於是使用了消息隊列,所以任務是串行執行的這點須要咱們注意。

參考

Android中的線程形態(二)(HandlerThread/IntentService)

【Android】Service那點事兒

相關文章
相關標籤/搜索