天天看點

IntentService和HandlerThread的使用以及源碼閱讀簡介使用源碼分析

IntentService和HandlerThread的使用以及源碼閱讀

  • 簡介
  • 使用
  • 源碼分析

簡介

IntentService是一種特殊的service,一般用來執行一些耗時任務,作用類似于Thread,但是相對于普通的thread,service的系統優先級更高,不容易被殺死。是以IntentService準确來說,适合用來執行一些,比較重要的背景任務。

而HandlerThread則是繼承thread的,一種特殊的thread,一般用來搭配IntentService使用而不單獨使用。

使用

MyIntentService.java

public class MyIntentService extends IntentService {


    /**
     * 是否正在運作
     */
    private boolean isRunning;

    /**
     *進度
     */
    private int count;

    public MyIntentService() {
        super("test");
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public MyIntentService(String name) {
        super(name);
    }


    @Override
    protected void onHandleIntent(Intent intent) {
        Logout.e("onHandleIntent"+intent.getStringExtra("name"));
        try {
            Thread.sleep(1000);
            isRunning = true;
            count = 0;
            while (isRunning) {
                count++;
                if (count >= 100) {
                    isRunning = false;
                }
                Thread.sleep(50);
                Logout.e("線程運作中..."+ count);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Logout.e("結束了任務");
    }



    @Override
    public void onDestroy() {
        super.onDestroy();
        Logout.e("線程結束運作..." + count);
    }

    public static class Logout{
        private static final String TAG = "Logout";
        public static void e(String conent){
            Log.d(TAG, "e: "+conent);
        }
    }

}
           
public classTestActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);

        startService(new Intent(this, MyIntentService.class));
        new Handler().post(new Runnable() {
            @Override
            public void run() {
            	//延遲一段時間,發送第二次消息
                Intent intent = new Intent(AsyncTaskActivity.this, MyIntentService.class);
                intent.putExtra("name", "helloWorld");
                startService(intent);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        handlerThread.quit();
        //      unbindService(serviceConnection);
    }
 }
           

上面就是簡單的使用IntentService的教程。 IntentService是一個抽象類,是以需要自己內建實作,這裡有兩點需要注意。

  • 自己實作的類需要提供無參的構造函數
  • IntentService 是在onHandleIntent中處理耗時操作,這裡的intent 就是startService中的intent.

源碼分析

我們首先來看一下IntentService 的oncreate的代碼

@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 + "]");
        thread.start();

		//使用HandlerThread 的looper 構造一個handler,這樣就可以從HandlerThread接收發送消息
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
           

HandlerThread中比較值得關注的就是run方法。

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

這裡的代碼也比較簡單,流程基本上就是在非ui thread中建構Handler的标準流程,然後會走到 Looper.loop();中進入死循環。是以HandlerThread在使用結束以後,需要記得調用quit方法,停止死循環。

關注完oncreate方法,我們來着重觀察一下IntentServcie的onstart 和 onStartCommand方法

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

    /**
     * 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(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }
           

可以看到這裡利用了onStartCommand 每次startService每次都會調用onStartCommand的特點,用來給IntentService傳遞消息。IntentService收到消息後,就會調用mServiceHandler 将消息發送出去。這裡主要的作用是将主線程的資訊傳遞到HandlerThread。是以接下來,我們來看下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);
        }
    }
           

重要的代碼,一共就兩句話,而onHandleIntent 就是我們需要在自己實作的IntentService中覆寫的方法,也就是用來處理耗時事件的方法。

如果處理完onHandleIntent事件以後,service會嘗試調用stopSelf去結束掉整個服務。但是這個結束服務并不是一個強制性的操作,如果service仍然有事件未處理,就不會結束掉。這裡就不在細究,大家記住這個結論就行了。

而且由于handler的消息阻塞機制,這裡的事件并不會并發執行,而是類似SingleThreadExecutor的單任務串行執行。