Android異步相關-AsyncTask/HandlerThread/IntentService

AysncTask

AsyncTask本質上是一個Handler和線程池的封裝,線程池用來異步處理後臺任務,handler用來發送消息進行UI方面的交互
優點:

  • 適合簡單短時的異步任務,可以同時爆發數量較大的異步任務(支持線程池,任務隊列128個,最多同時併發5個)
  • 過程可控(即onPreExecute、doInBackground、onPostExecute等)

AsyncTask

public final AsyncTask<Params, Progress, Result> execute(Params... params) {  
    return executeOnExecutor(sDefaultExecutor, params);  
}  
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,  
        Params... params) {  
    if (mStatus != Status.PENDING) {  
        switch (mStatus) {  
            case RUNNING:  
                throw new IllegalStateException("Cannot execute task:"  
                        + " the task is already running.");  
            case FINISHED:  
                throw new IllegalStateException("Cannot execute task:"  
                        + " the task has already been executed "  
                        + "(a task can be executed only once)");  
        }  
    }  
    mStatus = Status.RUNNING;  
    onPreExecute();  
    mWorker.mParams = params;  
    exec.execute(mFuture);  
    return this;  
}  

這裏調用onPreExecute後開始觸發線程池 ,跑子線程。線程池中最終運行mFuture的run方法,run調用innerRun

void innerRun() {  
    if (!compareAndSetState(READY, RUNNING))  
        return;  
    runner = Thread.currentThread();  
    if (getState() == RUNNING) { // recheck after setting thread  
        V result;  
        try {  
            result = callable.call();  
        } catch (Throwable ex) {  
            setException(ex);  
            return;  
        }  
        set(result);  
    } else {  
        releaseShared(0); // cancel  
    }  
}  

這邊的callable.call其實就是調用WorkerRunnable.call

public Result call() throws Exception {  
    mTaskInvoked.set(true);  
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
    return postResult(doInBackground(mParams));  
} 

很明顯就是在線程內部調用了doInBackground,之後把doInBackground的結果作爲參數調用postResult;這裏先揭祕下,postResult會利用Handler回到主線程調用onPostExecute

private Result postResult(Result result) {  
    Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,  
            new AsyncTaskResult<Result>(this, result));  
    message.sendToTarget();  
    return result;  
} 
private static class InternalHandler extends Handler {  
    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})  
    @Override  
    public void handleMessage(Message msg) {  
        AsyncTaskResult result = (AsyncTaskResult) msg.obj;  
        switch (msg.what) {  
            case MESSAGE_POST_RESULT:  
                // There is only one result  
                result.mTask.finish(result.mData[0]);  
                break;  
            case MESSAGE_POST_PROGRESS:  
                result.mTask.onProgressUpdate(result.mData);  
                break;  
        }  
    }  
}  

可以看到這邊有handleMessage有兩個分支一個分支finish最終調用onPostExecute,另一個onProgressUpdate是更新進度的

HandlerThread

HandlerThread本質上就是一個Thread和Looper的封裝。與AsyncTask的區別在於,AsyncTask適合短時併發數多的小任務,HandlerThread適合耗時多數據量大的任務。但HandlerThread同時只能執行一個任務,多個任務會以隊列的形式串行執行。
優點:

  • 結構清晰,功能定義明確
  • 對於多個後臺任務時,簡單,清晰

用法

       HandlerThread mHandlerThread = new HandlerThread("MyHandlerThread");
        mHandlerThread.start();
        //HandlerThread內部的Looper,這邊的代碼會在HandlerThread裏的子線程中執行
        Handler handler = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //這裏可以執行異步任務,執行完可調用mMainHandler回到主線程刷新UI
            }
        };
        //發送消息觸發HandlerThread的handler,執行異步任務
        handler.sendEmptyMessage(1);
        //這種用法與sendMessage差不多,只不過這邊的Message自帶裏處理Callback即Runnable的處理
        handler.post(new Runnable() {
            @Override
            public void run() {

            }
        });
        //主線程的Looper
        Handler mMainHandler = new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //更新UI
            }
        };
        //清空HandlerThread內部消息
        mHandlerThread.quit();//清空所有消息
        mHandlerThread.quitSafely();//只清空延遲消息

HandlerThread源碼

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    protected void onLooperPrepared() {
    }
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();    //喚醒其他線程的等待鎖,這邊是爲了喚醒getLooper()方法中的等待鎖
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }        
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        // 線程開始,該方法會一直等待Looper對象創建完成纔會執行,               
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }    
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }    
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }    
    public int getThreadId() {
        return mTid;
    }
}

源碼很短,沒有太多難點主要是一些細節處理。

IntentService

IntentService本質上是一個Service和HandlerThread的封裝。
優點:

  • IntentService創建獨立線程來處理Intent請求
  • IntentService處理請求後會自動停止

注意點:IntentService只能使用bindService,如果用startService來啓動的話則onHandleIntent則不會被調用,失去IntenService的 意義,變得跟普通Service一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章