IntentService中的耗時操作

文章目錄


由於Service和Broadcast都是運行在主線程中,所以在這兩個裏面我們無法做一些長時間的耗時操作,要執行耗時操作可以用異步線程AsyncTask或者IntentServie。IntentServie的好處是調用玩後會自己關閉service。

用法

調用基本是重寫IntentService,然後生成intent,startService。

public class MyIntentService extends IntentService {
	//必須創建構造方法
    //因爲IntentService裏面已經有個一個構造方法了,構建的時候jvm不會再構造一個構造方法了。
    //你繼承IntentService如果不添加構造方法將沒有構造方法。jvm會報錯。
    //java.lang.InstantiationException: java.lang.Class<***.MyService> has no zero argument constructor
    public MyIntentService () {
        super("");
    }  

    //實現你要做的內容
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        System.out.println("工作線程是: "+Thread.currentThread().getName());
        String task = intent.getStringExtra("task");
        System.out.println("任務是 :"+task);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
	//在Manifest.xml中註冊服務
	//調用方式。
        Intent intent = new Intent(this,MyIntentService .class);
        intent.putExtra("task","播放音樂");
        startService(intent);

原理

IntentService裏面可以執行耗時操作,下面看下它是怎麼實現的。

package android.app;

import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

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) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }


    public IntentService(String name) {
        super();
        mName = name;
    }


    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();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable 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(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }


    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }


    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

IntentService 繼承Service 。它裏面主要是開了一個HandlerThread,執行耗時的操作的內容就在工作線程裏面操作。

在onCreate的時候執時候,新建了一個HandlerThread

    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 thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
			
		//建立線程的Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

HandlerThread繼承了Thread,實現的run方法是建立一套安卓的異步消息隊列的。

//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;
    }
    

在工作的時候,HandlerThread的onStart放就新建一個message放到handler裏面。

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

Handler是另外定義的,對應到內部類是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);
        }
    }

這裏可以看出,執行handleMessage時候先執行onHandleIntent((Intent)msg.obj);,然後在執行stopSelf(msg.arg1);onHandleIntent是你自己定義的要執行的內容,stopSelf是結束service。也是就是說,執行完耗時操作後,會關掉service。

//Service 裏面的
    /**
     * Stop the service, if it was previously started.  This is the same as
     * calling {@link android.content.Context#stopService} for this particular service.
     *  
     * @see #stopSelfResult(int)
     */
    public final void stopSelf() {
        stopSelf(-1);
    }

    /**
     * Old version of {@link #stopSelfResult} that doesn't return a result.
     *  
     * @see #stopSelfResult
     */
    public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章