青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

xiaoguozi's Blog
Pay it forword - 我并不覺的自豪,我所嘗試的事情都失敗了······習慣原本生活的人不容易改變,就算現狀很糟,他們也很難改變,在過程中,他們還是放棄了······他們一放棄,大家就都是輸家······讓愛傳出去,很困難,也無法預料,人們需要更細心的觀察別人,要隨時注意才能保護別人,因為他們未必知道自己要什么·····

我們知道,Android應用程序是通過消息來驅動的,即在應用程序的主線程(UI線程)中有一個消息循環,負責處理消息隊列中的消息。我們也知 道,Android應用程序是支持多線程的,即可以創建子線程來執行一些計算型的任務,那么,這些子線程能不能像應用程序的主線程一樣具有消息循環呢?這 些子線程又能不能往應用程序的主線程中發送消息呢?本文將分析Android應用程序線程消息處理模型,為讀者解答這兩個問題

 

        在開發Android應用程序中,有時候我們需要在應用程序中創建一些常駐的子線程來不定期地執行一些不需要與應用程序界面交互的計算型的任務。如果這些 子線程具有消息循環,那么它們就能夠常駐在應用程序中不定期的執行一些計算型任務了:當我們需要用這些子線程來執行任務時,就往這個子線程的消息隊列中發 送一個消息,然后就可以在子線程的消息循環中執行我們的計算型任務了。我們在前面一篇文章Android系統默認Home應用程序(Launcher)的 啟動過程源代碼分析中,介紹Launcher的啟動過程時,在Step 15(LauncherModel.startLoader)中,Launcher就是通過往一個子線程的消息隊列中發送一個消息 (sWorker.post(mLoaderTask)),然后子線程就會在它的消息循環中處理這個消息的時候執行從 PackageManagerService中獲取系統中已安裝應用程序的信息列表的任務,即調用Step 16中的LoaderTask.run函數。

 

        在開發Android應用程序中,有時候我們又需要在應用程序中創建一些子線程來執行一些需要與應用程序界面進交互的計算型任務。典型的應用場景是當我們要從網上下載文 件時,為了不使主線程被阻塞,我們通常創建一個子線程來負責下載任務,同時,在下載的過程,將下載進度以百分比的形式在應用程序的界面上顯示出來,這樣就 既不會阻塞主線程的運行,又能獲得良好的用戶體驗。但是,我們知道,Android應用程序的子線程是不可以操作主線程的UI的,那么,這個負責下載任務 的子線程應該如何在應用程序界面上顯示下載的進度呢?如果我們能夠在子線程中往主線程的消息隊列中發送消息,那么問題就迎刃而解了,因為發往主線程消息隊 列的消息最終是由主線程來處理的,在處理這個消息的時候,我們就可以在應用程序界面上顯示下載進度了。

 

        上面提到的這兩種情況,Android系統都為我們提供了完善的解決方案,前者可以通過使用HandlerThread類來實現,而后者可以使用 AsyncTask類來實現,本文就詳細這兩個類是如何實現的。不過,為了更好地理解HandlerThread類和AsyncTask類的實現,我們先 來看看應用程序的主線程的消息循環模型是如何實現的。

 

        1. 應用程序主線程消息循環模型

 

        在前面一篇文章Android應用程序進程啟動過程的源代碼分析一文中,我們已經分析應用程序進程(主線程)的啟動過程了,這里主要是針對它的消息循環模 型作一個總結。當運行在Android應用程序框架層中的ActivityManagerService決定要為當前啟動的應用程序創建一個主線程的時 候,它會在ActivityManagerService中的startProcessLocked成員函數調用Process類的靜態成員函數 start為當前應用程序創建一個主線程:

 

 

view plaincopy to clipboardprint?public final class ActivityManagerService extends ActivityManagerNative     

        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {     

     

    ......     

     

    private final void startProcessLocked(ProcessRecord app,     

                String hostingType, String hostingNameStr) {     

     

        ......     

     

        try {     

            int uid = app.info.uid;     

            int[] gids = null;     

            try {     

                gids = mContext.getPackageManager().getPackageGids(     

                    app.info.packageName);     

            } catch (PackageManager.NameNotFoundException e) {     

                ......     

            }     

                 

            ......     

     

            int debugFlags = 0;     

                 

            ......     

                 

            int pid = Process.start("android.app.ActivityThread",     

                mSimpleProcessManagement ? app.processName : null, uid, uid,     

                gids, debugFlags, null);     

                 

            ......     

     

        } catch (RuntimeException e) {     

                 

            ......     

     

        }     

    }     

     

    ......     

     

}     

public final class ActivityManagerService extends ActivityManagerNative   

        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   

   

    ......    

   

    private final void startProcessLocked(ProcessRecord app,   

                String hostingType, String hostingNameStr) {   

   

        ......   

   

        try {   

            int uid = app.info.uid;   

            int[] gids = null;   

            try {   

                gids = mContext.getPackageManager().getPackageGids(   

                    app.info.packageName);   

            } catch (PackageManager.NameNotFoundException e) {   

                ......   

            }   

               

            ......   

   

            int debugFlags = 0;   

               

            ......   

               

            int pid = Process.start("android.app.ActivityThread",   

                mSimpleProcessManagement ? app.processName : null, uid, uid,   

                gids, debugFlags, null);   

               

            ......   

   

        } catch (RuntimeException e) {   

               

            ......   

   

        }   

    }   

   

    ......   

   

}            這里我們主要關注Process.start函數的第一個參數“android.app.ActivityThread”,它表示要在當前新建的線程中加 載android.app.ActivityThread類,并且調用這個類的靜態成員函數main作為應用程序的入口點。ActivityThread 類定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:

 

 

view plaincopy to clipboardprint?public final class ActivityThread {   

    ......   

   

    public static final void main(String[] args) {   

        ...... 

   

        Looper.prepareMainLooper();   

          

        ......   

   

        ActivityThread thread = new ActivityThread();   

        thread.attach(false);   

   

        ......  

        Looper.loop();   

   

        ......  

   

        thread.detach();   

        ......   

    }   

   

    ......   

}   

public final class ActivityThread { 

    ...... 

 

    public static final void main(String[] args) { 

        ......

 

        Looper.prepareMainLooper(); 

        

        ...... 

 

        ActivityThread thread = new ActivityThread(); 

        thread.attach(false); 

 

        ......

        Looper.loop(); 

 

        ......

 

        thread.detach(); 

        ...... 

    } 

 

    ...... 

}          在這個main函數里面,除了創建一個ActivityThread實例外,就是在進行消息循環了。

 

        在進行消息循環之前,首先會通過Looper類的靜態成員函數prepareMainLooper為當前線程準備一個消息循環對象。Looper類定義在 frameworks/base/core/java/android/os/Looper.java文件中:

 

 

view plaincopy to clipboardprint?public class Looper { 

    ...... 

 

    // sThreadLocal.get() will return null unless you've called prepare().  

    private static final ThreadLocal sThreadLocal = new ThreadLocal(); 

 

    ...... 

 

    private static Looper mMainLooper = null; 

 

    ...... 

 

    public static final void prepare() { 

        if (sThreadLocal.get() != null) { 

            throw new RuntimeException("Only one Looper may be created per thread"); 

        } 

        sThreadLocal.set(new Looper()); 

    } 

 

    ...... 

 

    public static final void prepareMainLooper() { 

        prepare(); 

        setMainLooper(myLooper()); 

        ...... 

    } 

 

    private synchronized static void setMainLooper(Looper looper) { 

        mMainLooper = looper; 

    } 

 

    public synchronized static final Looper getMainLooper() { 

        return mMainLooper; 

    } 

 

    ...... 

 

    public static final Looper myLooper() { 

        return (Looper)sThreadLocal.get(); 

    } 

 

    ...... 

public class Looper {

......

 

// sThreadLocal.get() will return null unless you've called prepare().

private static final ThreadLocal sThreadLocal = new ThreadLocal();

 

......

 

private static Looper mMainLooper = null;

 

......

 

public static final void prepare() {

if (sThreadLocal.get() != null) {

throw new RuntimeException("Only one Looper may be created per thread");

}

sThreadLocal.set(new Looper());

}

 

......

 

public static final void prepareMainLooper() {

prepare();

setMainLooper(myLooper());

......

}

 

private synchronized static void setMainLooper(Looper looper) {

mMainLooper = looper;

}

 

public synchronized static final Looper getMainLooper() {

return mMainLooper;

}

 

......

 

public static final Looper myLooper() {

return (Looper)sThreadLocal.get();

}

 

......

}

 

        Looper類的靜態成員函數prepareMainLooper是專門應用程序的主線程調用的,應用程序的其它子線程都不應該調用這個函數來在本線程中 創建消息循環對象,而應該調用prepare函數來在本線程中創建消息循環對象,下一節我們介紹一個線程類HandlerThread 時將會看到。

 

        為什么要為應用程序的主線程專門準備一個創建消息循環對象的函數呢?這是為了讓其它地方能夠方便地通過Looper類的getMainLooper函數來 獲得應用程序主線程中的消息循環對象。獲得應用程序主線程中的消息循環對象又有什么用呢?一般就是為了能夠向應用程序主線程發送消息了。

 

        在prepareMainLooper函數中,首先會調用prepare函數在本線程中創建一個消息循環對象,然后將這個消息循環對象放在線程局部變量sThreadLocal中:

 

 

view plaincopy to clipboardprint?sThreadLocal.set(new Looper()); 

sThreadLocal.set(new Looper());        接著再將這個消息循環對象通過調用setMainLooper函數來保存在Looper類的靜態成員變量mMainLooper中:

 

 

view plaincopy to clipboardprint?mMainLooper = looper; 

mMainLooper = looper;       這樣,其它地方才可以調用getMainLooper函數來獲得應用程序主線程中的消息循環對象。

 

       消息循環對象創建好之后,回到ActivityThread類的main函數中,接下來,就是要進入消息循環了:

 

 

view plaincopy to clipboardprint?Looper.loop();  

Looper.loop();         Looper類具體是如何通過loop函數進入消息循環以及處理消息隊列中的消息,可以參考前面一篇文章Android應用程序消息處理機制 (Looper、Handler)分析,這里就不再分析了,我們只要知道ActivityThread類中的main函數執行了這一步之后,就為應用程序 的主線程準備好消息循環就可以了。

 

        2. 應用程序子線程消息循環模型

 

        在Java框架中,如果我們想在當前應用程序中創建一個子線程,一般就是通過自己實現一個類,這個類繼承于Thread類,然后重載Thread類的 run函數,把我們想要在這個子線程執行的任務都放在這個run函數里面實現。最后實例這個自定義的類,并且調用它的start函數,這樣一個子線程就創 建好了,并且會調用這個自定義類的run函數。但是當這個run函數執行完成后,子線程也就結束了,它沒有消息循環的概念。

 

        前面說過,有時候我們需要在應用程序中創建一些常駐的子線程來不定期地執行一些計算型任務,這時候就可以考慮使用Android系統提供的HandlerThread類了,它具有創建具有消息循環功能的子線程的作用。

 

        HandlerThread類實現在frameworks/base/core/java/android/os/HandlerThread.java文件中,這里我們通過使用情景來有重點的分析它的實現。

 

        在前面一篇文章Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析中,我們分析了Launcher的啟動過程,其中在 Step 15(LauncherModel.startLoader)和Step 16(LoaderTask.run)中,Launcher會通過創建一個HandlerThread類來實現在一個子線程加載系統中已經安裝的應用程序 的任務:

 

 

view plaincopy to clipboardprint?public class LauncherModel extends BroadcastReceiver { 

    ...... 

 

    private LoaderTask mLoaderTask; 

 

    private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader"); 

    static { 

        sWorkerThread.start(); 

    } 

    private static final Handler sWorker = new Handler(sWorkerThread.getLooper()); 

 

    ...... 

 

    public void startLoader(Context context, boolean isLaunching) {   

        ......   

 

        synchronized (mLock) {   

            ......   

 

            // Don't bother to start the thread if we know it's not going to do anything    

            if (mCallbacks != null && mCallbacks.get() != null) {   

                ...... 

 

                mLoaderTask = new LoaderTask(context, isLaunching);   

                sWorker.post(mLoaderTask);   

            }   

        }   

    }   

 

    ...... 

 

    private class LoaderTask implements Runnable {   

        ......   

 

        public void run() {   

            ......   

 

            keep_running: {   

                ......   

 

                // second step    

                if (loadWorkspaceFirst) {   

                    ......   

                    loadAndBindAllApps();   

                } else {   

                    ......   

                }   

 

                ......   

            }   

 

            ......   

        }   

 

        ......   

    }  

 

    ...... 

public class LauncherModel extends BroadcastReceiver {

......

 

private LoaderTask mLoaderTask;

 

private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");

static {

sWorkerThread.start();

}

private static final Handler sWorker = new Handler(sWorkerThread.getLooper());

 

......

 

public void startLoader(Context context, boolean isLaunching) { 

...... 

 

synchronized (mLock) { 

...... 

 

// Don't bother to start the thread if we know it's not going to do anything 

if (mCallbacks != null && mCallbacks.get() != null) { 

......

 

mLoaderTask = new LoaderTask(context, isLaunching); 

sWorker.post(mLoaderTask); 

 

......

 

private class LoaderTask implements Runnable { 

...... 

 

public void run() { 

...... 

 

keep_running: { 

...... 

 

// second step 

if (loadWorkspaceFirst) { 

...... 

loadAndBindAllApps(); 

} else { 

...... 

 

...... 

 

...... 

 

...... 

}

 

......

}        在這個LauncherModel類中,首先創建了一個HandlerThread對象:

 

 

view plaincopy to clipboardprint?private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader"); 

private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");        接著調用它的start成員函數來啟動一個子線程:

 

 

view plaincopy to clipboardprint?static { 

    sWorkerThread.start(); 

static {

    sWorkerThread.start();

}        接著還通過這個HandlerThread對象的getLooper函數來獲得這個子線程中的消息循環對象,并且使用這個消息循環創建對象來創建一個Handler:

 

 

view plaincopy to clipboardprint?private static final Handler sWorker = new Handler(sWorkerThread.getLooper()); 

private static final Handler sWorker = new Handler(sWorkerThread.getLooper());        有了這個Handler對象sWorker之后,我們就可以往這個子線程中發送消息,然后在處理這個消息的時候執行加載系統中已經安裝的應用程序的任務 了,在startLoader函數中:

 

 

view plaincopy to clipboardprint?mLoaderTask = new LoaderTask(context, isLaunching);   

sWorker.post(mLoaderTask);   

mLoaderTask = new LoaderTask(context, isLaunching); 

sWorker.post(mLoaderTask);          這里的mLoaderTask是一個LoaderTask對象,它實現了Runnable接口,因此,可以把這個LoaderTask對象作為參數傳給 sWorker.post函數。在sWorker.post函數里面,會把這個LoaderTask對象封裝成一個消息,并且放入這個子線程的消息隊列中 去。當這個子線程的消息循環處理這個消息的時候,就會調用這個LoaderTask對象的run函數,因此,我們就可以在LoaderTask對象的 run函數中通過調用loadAndBindAllApps來執行加載系統中已經安裝的應用程序的任務了。

 

        了解了HanderThread類的使用方法之后,我們就可以重點地來分析它的實現了:

 

 

view plaincopy to clipboardprint?public class HandlerThread extends Thread { 

    ...... 

    private Looper mLooper; 

 

    public HandlerThread(String name) { 

        super(name); 

        ...... 

    } 

 

    ...... 

 

    public void run() { 

        ...... 

        Looper.prepare(); 

        synchronized (this) { 

            mLooper = Looper.myLooper(); 

            ...... 

        } 

        ...... 

        Looper.loop(); 

        ...... 

    } 

 

    public Looper getLooper() { 

        ...... 

        return mLooper; 

    } 

 

    ...... 

public class HandlerThread extends Thread {

......

private Looper mLooper;

 

public HandlerThread(String name) {

super(name);

......

}

 

......

 

public void run() {

......

Looper.prepare();

synchronized (this) {

mLooper = Looper.myLooper();

......

}

......

Looper.loop();

......

}

 

public Looper getLooper() {

......

return mLooper;

}

 

......

}        首先我們看到的是,Handler類繼承了Thread類,因此,通過它可以在應用程序中創建一個子線程,其次我們看到在它的run函數中,會進入一個消息循環中,因此,這個子線程可以常駐在應用程序中,直到它接收收到一個退出消息為止。

 

        在run函數中,首先是調用Looper類的靜態成員函數prepare來準備一個消息循環對象:

 

 

view plaincopy to clipboardprint?Looper.prepare(); 

Looper.prepare();        然后通過Looper類的myLooper成員函數將這個子線程中的消息循環對象保存在HandlerThread類中的成員變量mLooper中:

 

 

view plaincopy to clipboardprint?mLooper = Looper.myLooper(); 

mLooper = Looper.myLooper();        這樣,其它地方就可以方便地通過它的getLooper函數來獲得這個消息循環對象了,有了這個消息循環對象后,就可以往這個子線程的消息隊列中發送消息,通知這個子線程執行特定的任務了。

 

        最在這個run函數通過Looper類的loop函數進入消息循環中:

 

 

view plaincopy to clipboardprint?Looper.loop(); 

Looper.loop();        這樣,一個具有消息循環的應用程序子線程就準備就緒了。

 

        HandlerThread類的實現雖然非常簡單,當然這得益于Java提供的Thread類和Android自己本身提供的Looper類,但是它的想法卻非常周到,為應用程序開發人員提供了很大的方便。

        3. 需要與UI交互的應用程序子線程消息模型

 

 

        前面說過,我們開發應用程序的時候,經常中需要創建一個子線程來在后臺執行一個特定的計算任務,而在這個任務計算的過程中,需要不斷地將計算進度或者計算 結果展現在應用程序的界面中。典型的例子是從網上下載文件,為了不阻塞應用程序的主線程,我們開辟一個子線程來執行下載任務,子線程在下載的同時不斷地將 下載進度在應用程序界面上顯示出來,這樣做出來程序就非常友好。由于子線程不能直接操作應用程序的UI,因此,這時候,我們就可以通過往應用程序的主線程 中發送消息來通知應用程序主線程更新界面上的下載進度。因為類似的這種情景在實際開發中經常碰到,Android系統為開發人員提供了一個異步任務類 (AsyncTask)來實現上面所說的功能,即它會在一個子線程中執行計算任務,同時通過主線程的消息循環來獲得更新應用程序界面的機會。

 

        為了更好地分析AsyncTask的實現,我們先舉一個例子來說明它的用法。在前面一篇文章Android系統中的廣播(Broadcast)機制簡要介 紹和學習計劃中,我們開發了一個應用程序Broadcast,其中使用了AsyncTask來在一個線程在后臺在執行計數任務,計數過程通過廣播 (Broadcast)來將中間結果在應用程序界面上顯示出來。在這個例子中,使用廣播來在應用程序主線程和子線程中傳遞數據不是最優的方法,當時只是為 了分析Android系統的廣播機制而有意為之的。在本節內容中,我們稍微這個例子作一個簡單的修改,就可以通過消息的方式來將計數過程的中間結果在應用 程序界面上顯示出來。

 

        為了區別Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中使用的應用程序Broadcast,我們將本節中使用的應用程序 命名為Counter。首先在Android源代碼工程中創建一個Android應用程序工程,名字就為Counter,放在 packages/experimental目錄下。關于如何獲得Android源代碼工程,請參考在Ubuntu上下載、編譯和安裝Android最新 源代碼一文;關于如何在Android源代碼工程中創建應用程序工程,請參考在Ubuntu上為Android系統內置Java應用程序測試 Application Frameworks層的硬件服務一文。這個應用程序工程定義了一個名為shy.luo.counter的package,這個例子的源代碼主要就是實現 在這個目錄下的Counter.java文件中:

 

 

view plaincopy to clipboardprint?package shy.luo.counter; 

 

import android.app.Activity; 

import android.content.ComponentName; 

import android.content.Context; 

import android.content.Intent; 

import android.content.IntentFilter; 

import android.os.Bundle; 

import android.os.AsyncTask; 

import android.util.Log; 

import android.view.View; 

import android.view.View.OnClickListener; 

import android.widget.Button; 

import android.widget.TextView; 

 

public class Counter extends Activity implements OnClickListener { 

    private final static String LOG_TAG = "shy.luo.counter.Counter"; 

 

    private Button startButton = null; 

    private Button stopButton = null; 

    private TextView counterText = null; 

 

    private AsyncTask<Integer, Integer, Integer> task = null; 

    private boolean stop = false; 

 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.main); 

 

        startButton = (Button)findViewById(R.id.button_start); 

        stopButton = (Button)findViewById(R.id.button_stop); 

        counterText = (TextView)findViewById(R.id.textview_counter); 

 

        startButton.setOnClickListener(this); 

        stopButton.setOnClickListener(this); 

 

        startButton.setEnabled(true); 

        stopButton.setEnabled(false); 

 

  

        Log.i(LOG_TAG, "Main Activity Created."); 

    } 

 

 

    @Override 

    public void onClick(View v) { 

        if(v.equals(startButton)) { 

            if(task == null) { 

                task = new CounterTask(); 

                task.execute(0); 

 

                startButton.setEnabled(false); 

                stopButton.setEnabled(true); 

            } 

        } else if(v.equals(stopButton)) { 

            if(task != null) { 

                stop = true; 

                task = null; 

 

                startButton.setEnabled(true); 

                stopButton.setEnabled(false); 

            } 

        } 

    } 

 

    class CounterTask extends AsyncTask<Integer, Integer, Integer> { 

        @Override 

        protected Integer doInBackground(Integer... vals) { 

            Integer initCounter = vals[0]; 

 

            stop = false; 

            while(!stop) { 

                publishProgress(initCounter); 

 

                try { 

                    Thread.sleep(1000); 

                } catch (InterruptedException e) { 

                    e.printStackTrace(); 

                } 

 

                initCounter++; 

            } 

 

            return initCounter; 

        } 

 

        @Override 

        protected void onProgressUpdate(Integer... values) { 

            super.onProgressUpdate(values); 

 

            String text = values[0].toString(); 

            counterText.setText(text); 

        } 

 

        @Override 

        protected void onPostExecute(Integer val) { 

            String text = val.toString(); 

            counterText.setText(text); 

        } 

    }; 

package shy.luo.counter;

 

import android.app.Activity;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.Bundle;

import android.os.AsyncTask;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

 

public class Counter extends Activity implements OnClickListener {

private final static String LOG_TAG = "shy.luo.counter.Counter";

 

private Button startButton = null;

private Button stopButton = null;

private TextView counterText = null;

 

private AsyncTask<Integer, Integer, Integer> task = null;

private boolean stop = false;

 

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

 

startButton = (Button)findViewById(R.id.button_start);

stopButton = (Button)findViewById(R.id.button_stop);

counterText = (TextView)findViewById(R.id.textview_counter);

 

startButton.setOnClickListener(this);

stopButton.setOnClickListener(this);

 

startButton.setEnabled(true);

stopButton.setEnabled(false);

 

 

Log.i(LOG_TAG, "Main Activity Created.");

}

 

 

@Override

public void onClick(View v) {

if(v.equals(startButton)) {

if(task == null) {

task = new CounterTask();

task.execute(0);

 

startButton.setEnabled(false);

stopButton.setEnabled(true);

}

} else if(v.equals(stopButton)) {

if(task != null) {

stop = true;

task = null;

 

startButton.setEnabled(true);

stopButton.setEnabled(false);

}

}

}

 

class CounterTask extends AsyncTask<Integer, Integer, Integer> {

@Override

protected Integer doInBackground(Integer... vals) {

Integer initCounter = vals[0];

 

stop = false;

while(!stop) {

publishProgress(initCounter);

 

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

 

initCounter++;

}

 

return initCounter;

}

 

@Override

protected void onProgressUpdate(Integer... values) {

super.onProgressUpdate(values);

 

String text = values[0].toString();

counterText.setText(text);

}

 

@Override

protected void onPostExecute(Integer val) {

String text = val.toString();

counterText.setText(text);

}

};

}        這個計數器程序很簡單,它在界面上有兩個按鈕Start和Stop。點擊Start按鈕時,便會創建一個CounterTask實例task,然后調用它 的execute函數就可以在應用程序中啟動一個子線程,并且通過調用這個CounterTask類的doInBackground函數來執行計數任務。 在計數的過程中,會通過調用publishProgress函數來將中間結果傳遞到onProgressUpdate函數中去,在 onProgressUpdate函數中,就可以把中間結果顯示在應用程序界面了。點擊Stop按鈕時,便會通過設置變量stop為true,這 樣,CounterTask類的doInBackground函數便會退出循環,然后將結果返回到onPostExecute函數中去,在 onPostExecute函數,會把最終計數結果顯示在用程序界面中。

 

       在這個例子中,我們需要注意的是:

 

       A. CounterTask類繼承于AsyncTask類,因此它也是一個異步任務類;

 

       B. CounterTask類的doInBackground函數是在后臺的子線程中運行的,這時候它不可以操作應用程序的界面;

 

       C. CounterTask類的onProgressUpdate和onPostExecute兩個函數是應用程序的主線程中執行,它們可以操作應用程序的界面。

 

       關于C這一點的實現原理,我們在后面會分析到,這里我們先完整地介紹這個例子,以便讀者可以參考做一下實驗。

 

       接下來我們再看看應用程序的配置文件AndroidManifest.xml:

 

 

view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?> 

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 

      package="shy.luo.counter" 

      android:versionCode="1" 

      android:versionName="1.0"> 

    <application android:icon="@drawable/icon" android:label="@string/app_name"> 

        <activity android:name=".Counter" 

                  android:label="@string/app_name"> 

            <intent-filter> 

                <action android:name="android.intent.action.MAIN" /> 

                <category android:name="android.intent.category.LAUNCHER" /> 

            </intent-filter> 

        </activity> 

    </application> 

</manifest> 

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="shy.luo.counter"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".Counter"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

</manifest>       這個配置文件很簡單,我們就不介紹了。

 

       再來看應用程序的界面文件,它定義在res/layout/main.xml文件中:

 

 

view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?>   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   

    android:orientation="vertical"   

    android:layout_width="fill_parent"   

    android:layout_height="fill_parent"    

    android:gravity="center">   

    <LinearLayout   

        android:layout_width="fill_parent"   

        android:layout_height="wrap_content"   

        android:layout_marginBottom="10px"   

        android:orientation="horizontal"    

        android:gravity="center">   

        <TextView     

        android:layout_width="wrap_content"    

            android:layout_height="wrap_content"    

            android:layout_marginRight="4px"   

            android:gravity="center"   

            android:text="@string/counter">   

        </TextView>   

        <TextView     

            android:id="@+id/textview_counter"   

        android:layout_width="wrap_content"    

            android:layout_height="wrap_content"    

            android:gravity="center"   

            android:text="0">   

        </TextView>   

    </LinearLayout>   

    <LinearLayout   

        android:layout_width="fill_parent"   

        android:layout_height="wrap_content"   

        android:orientation="horizontal"    

        android:gravity="center">   

        <Button    

            android:id="@+id/button_start"   

            android:layout_width="wrap_content"   

            android:layout_height="wrap_content"   

            android:gravity="center"   

            android:text="@string/start">   

        </Button>   

        <Button    

            android:id="@+id/button_stop"   

            android:layout_width="wrap_content"   

            android:layout_height="wrap_content"   

            android:gravity="center"   

            android:text="@string/stop" >   

        </Button>    

     </LinearLayout>     

</LinearLayout>   

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 

    android:orientation="vertical" 

    android:layout_width="fill_parent" 

    android:layout_height="fill_parent"  

    android:gravity="center"> 

    <LinearLayout 

        android:layout_width="fill_parent" 

        android:layout_height="wrap_content" 

        android:layout_marginBottom="10px" 

        android:orientation="horizontal"  

        android:gravity="center"> 

        <TextView   

        android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:layout_marginRight="4px" 

            android:gravity="center" 

            android:text="@string/counter"> 

        </TextView> 

        <TextView   

            android:id="@+id/textview_counter" 

        android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:gravity="center" 

            android:text="0"> 

        </TextView> 

    </LinearLayout> 

    <LinearLayout 

        android:layout_width="fill_parent" 

        android:layout_height="wrap_content" 

        android:orientation="horizontal"  

        android:gravity="center"> 

        <Button  

            android:id="@+id/button_start" 

            android:layout_width="wrap_content" 

            android:layout_height="wrap_content" 

            android:gravity="center" 

            android:text="@string/start"> 

        </Button> 

        <Button  

            android:id="@+id/button_stop" 

            android:layout_width="wrap_content" 

            android:layout_height="wrap_content" 

            android:gravity="center" 

            android:text="@string/stop" > 

        </Button> 

     </LinearLayout>   

</LinearLayout>         這個界面配置文件也很簡單,等一下我們在模擬器把這個應用程序啟動起來后,就可以看到它的截圖了。

 

       應用程序用到的字符串資源文件位于res/values/strings.xml文件中:

 

 

view plaincopy to clipboardprint?<?xml version="1.0" encoding="utf-8"?>   

<resources>   

    <string name="app_name">Counter</string>   

    <string name="counter">Counter: </string>   

    <string name="start">Start Counter</string>   

    <string name="stop">Stop Counter</string>   

</resources>  

<?xml version="1.0" encoding="utf-8"?> 

<resources> 

    <string name="app_name">Counter</string> 

    <string name="counter">Counter: </string> 

    <string name="start">Start Counter</string> 

    <string name="stop">Stop Counter</string> 

</resources>        最后,我們還要在工程目錄下放置一個編譯腳本文件Android.mk:

 

 

view plaincopy to clipboardprint?LOCAL_PATH:= $(call my-dir)         

include $(CLEAR_VARS)         

         

LOCAL_MODULE_TAGS := optional         

         

LOCAL_SRC_FILES := $(call all-subdir-java-files)         

         

LOCAL_PACKAGE_NAME := Counter         

         

include $(BUILD_PACKAGE)   

LOCAL_PATH:= $(call my-dir)       

include $(CLEAR_VARS)       

       

LOCAL_MODULE_TAGS := optional       

       

LOCAL_SRC_FILES := $(call all-subdir-java-files)       

       

LOCAL_PACKAGE_NAME := Counter       

       

include $(BUILD_PACKAGE)         接下來就要編譯了。有關如何單獨編譯Android源代碼工程的模塊,以及如何打包system.img,請參考如何單獨編譯Android源代碼中的模塊一文。

       執行以下命令進行編譯和打包:

 

 

view plaincopy to clipboardprint?USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Counter           

USER-NAME@MACHINE-NAME:~/Android$ make snod 

USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Counter         

USER-NAME@MACHINE-NAME:~/Android$ make snod       這樣,打包好的Android系統鏡像文件system.img就包含我們前面創建的Counter應用程序了。

       再接下來,就是運行模擬器來運行我們的例子了。關于如何在Android源代碼工程中運行模擬器,請參考在Ubuntu上下載、編譯和安裝Android最新源代碼一文。

       執行以下命令啟動模擬器:

view plaincopy to clipboardprint?USER-NAME@MACHINE-NAME:~/Android$ emulator  

USER-NAME@MACHINE-NAME:~/Android$ emulator        最后我們就可以在Launcher中找到Counter應用程序圖標,把它啟動起來,點擊Start按鈕,就會看到應用程序界面上的計數器跑起來了:

 

 

 

 

        這樣,使用AsyncTask的例子就介紹完了,下面,我們就要根據上面對AsyncTask的使用情況來重點分析它的實現了。

 

        AsyncTask類定義在frameworks/base/core/java/android/os/AsyncTask.java文件中:

 

 

view plaincopy to clipboardprint?public abstract class AsyncTask<Params, Progress, Result> { 

    ...... 

 

    private static final BlockingQueue<Runnable> sWorkQueue = 

            new LinkedBlockingQueue<Runnable>(10); 

 

    private static final ThreadFactory sThreadFactory = new ThreadFactory() { 

        private final AtomicInteger mCount = new AtomicInteger(1); 

 

        public Thread newThread(Runnable r) { 

            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); 

        } 

    }; 

 

    ...... 

 

    private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, 

        MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory); 

 

    private static final int MESSAGE_POST_RESULT = 0x1; 

    private static final int MESSAGE_POST_PROGRESS = 0x2; 

    private static final int MESSAGE_POST_CANCEL = 0x3; 

 

    private static final InternalHandler sHandler = new InternalHandler(); 

 

    private final WorkerRunnable<Params, Result> mWorker; 

    private final FutureTask<Result> mFuture; 

 

    ...... 

 

    public AsyncTask() { 

        mWorker = new WorkerRunnable<Params, Result>() { 

            public Result call() throws Exception { 

                ...... 

                return doInBackground(mParams); 

            } 

        }; 

 

        mFuture = new FutureTask<Result>(mWorker) { 

            @Override 

            protected void done() { 

                Message message; 

                Result result = null; 

 

                try { 

                    result = get(); 

                } catch (InterruptedException e) { 

                    android.util.Log.w(LOG_TAG, e); 

                } catch (ExecutionException e) { 

                    throw new RuntimeException("An error occured while executing doInBackground()", 

                        e.getCause()); 

                } catch (CancellationException e) { 

                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, 

                        new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null)); 

                    message.sendToTarget(); 

                    return; 

                } catch (Throwable t) { 

                    throw new RuntimeException("An error occured while executing " 

                        + "doInBackground()", t); 

                } 

 

                message = sHandler.obtainMessage(MESSAGE_POST_RESULT, 

                    new AsyncTaskResult<Result>(AsyncTask.this, result)); 

                message.sendToTarget(); 

            } 

        }; 

    } 

 

    ...... 

 

    public final Result get() throws InterruptedException, ExecutionException { 

        return mFuture.get(); 

    } 

 

    ...... 

 

    public final AsyncTask<Params, Progress, Result> execute(Params... params) { 

        ...... 

 

        mWorker.mParams = params; 

        sExecutor.execute(mFuture); 

 

        return this; 

    } 

 

    ...... 

 

    protected final void publishProgress(Progress... values) { 

        sHandler.obtainMessage(MESSAGE_POST_PROGRESS, 

            new AsyncTaskResult<Progress>(this, values)).sendToTarget(); 

    } 

 

        private void finish(Result result) { 

                ...... 

                onPostExecute(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; 

                case MESSAGE_POST_CANCEL: 

                 result.mTask.onCancelled(); 

                 break; 

            } 

        } 

    } 

 

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { 

        Params[] mParams; 

    } 

 

    private static class AsyncTaskResult<Data> { 

        final AsyncTask mTask; 

        final Data[] mData; 

 

        AsyncTaskResult(AsyncTask task, Data... data) { 

            mTask = task; 

            mData = data; 

        } 

    } 

public abstract class AsyncTask<Params, Progress, Result> {

......

 

private static final BlockingQueue<Runnable> sWorkQueue =

new LinkedBlockingQueue<Runnable>(10);

 

private static final ThreadFactory sThreadFactory = new ThreadFactory() {

private final AtomicInteger mCount = new AtomicInteger(1);

 

public Thread newThread(Runnable r) {

return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());

}

};

 

......

 

private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,

MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

 

private static final int MESSAGE_POST_RESULT = 0x1;

private static final int MESSAGE_POST_PROGRESS = 0x2;

private static final int MESSAGE_POST_CANCEL = 0x3;

 

private static final InternalHandler sHandler = new InternalHandler();

 

private final WorkerRunnable<Params, Result> mWorker;

private final FutureTask<Result> mFuture;

 

......

 

public AsyncTask() {

mWorker = new WorkerRunnable<Params, Result>() {

public Result call() throws Exception {

......

return doInBackground(mParams);

}

};

 

mFuture = new FutureTask<Result>(mWorker) {

@Override

protected void done() {

Message message;

Result result = null;

 

try {

result = get();

} catch (InterruptedException e) {

android.util.Log.w(LOG_TAG, e);

} catch (ExecutionException e) {

throw new RuntimeException("An error occured while executing doInBackground()",

e.getCause());

} catch (CancellationException e) {

message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,

new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));

message.sendToTarget();

return;

} catch (Throwable t) {

throw new RuntimeException("An error occured while executing "

+ "doInBackground()", t);

}

 

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

new AsyncTaskResult<Result>(AsyncTask.this, result));

message.sendToTarget();

}

};

}

 

......

 

public final Result get() throws InterruptedException, ExecutionException {

return mFuture.get();

}

 

......

 

public final AsyncTask<Params, Progress, Result> execute(Params... params) {

......

 

mWorker.mParams = params;

sExecutor.execute(mFuture);

 

return this;

}

 

......

 

protected final void publishProgress(Progress... values) {

sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

new AsyncTaskResult<Progress>(this, values)).sendToTarget();

}

 

        private void finish(Result result) {

                ......

                onPostExecute(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;

        case MESSAGE_POST_CANCEL:

     result.mTask.onCancelled();

     break;

}

}

}

 

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {

Params[] mParams;

}

 

private static class AsyncTaskResult<Data> {

final AsyncTask mTask;

final Data[] mData;

 

AsyncTaskResult(AsyncTask task, Data... data) {

mTask = task;

mData = data;

}

}

}

        從AsyncTask的實現可以看出,當我們第一次創建一個AsyncTask對象時,首先會執行下面靜態初始化代碼創建一個線程池sExecutor:

 

 

view plaincopy to clipboardprint?private static final BlockingQueue<Runnable> sWorkQueue = 

    new LinkedBlockingQueue<Runnable>(10); 

 

private static final ThreadFactory sThreadFactory = new ThreadFactory() { 

    private final AtomicInteger mCount = new AtomicInteger(1); 

 

    public Thread newThread(Runnable r) { 

        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); 

    } 

}; 

 

...... 

 

private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, 

    MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory); 

private static final BlockingQueue<Runnable> sWorkQueue =

new LinkedBlockingQueue<Runnable>(10);

 

private static final ThreadFactory sThreadFactory = new ThreadFactory() {

private final AtomicInteger mCount = new AtomicInteger(1);

 

public Thread newThread(Runnable r) {

return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());

}

};

 

......

 

private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,

MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);        這里的ThreadPoolExecutor是Java提供的多線程機制之一,這里用的構造函數原型為:

 

 

view plaincopy to clipboardprint?ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,  

    BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) 

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,

    BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)        各個參數的意義如下:

 

        corePoolSize -- 線程池的核心線程數量

 

        maximumPoolSize -- 線程池的最大線程數量

 

        keepAliveTime -- 若線程池的線程數數量大于核心線程數量,那么空閑時間超過keepAliveTime的線程將被回收

 

        unit -- 參數keepAliveTime使用的時間單位

 

        workerQueue -- 工作任務隊列

 

        threadFactory -- 用來創建線程池中的線程

        簡單來說,ThreadPoolExecutor的運行機制是這樣的:每一個工作任務用一個Runnable對象來表示,當我們要把一個工作任務交給這個 線程池來執行的時候,就通過調用ThreadPoolExecutor的execute函數來把這個工作任務加入到線程池中去。此時,如果線程池中的線程 數量小于corePoolSize,那么就會調用threadFactory接口來創建一個新的線程并且加入到線程池中去,再執行這個工作任務;如果線程 池中的線程數量等于corePoolSize,但是工作任務隊列workerQueue未滿,則把這個工作任務加入到工作任務隊列中去等待執行;如果線程 池中的線程數量大于corePoolSize,但是小于maximumPoolSize,并且工作任務隊列workerQueue已經滿了,那么就會調用 threadFactory接口來創建一個新的線程并且加入到線程池中去,再執行這個工作任務;如果線程池中的線程量已經等于 maximumPoolSize了,并且工作任務隊列workerQueue也已經滿了,這個工作任務就被拒絕執行了。

 

        創建好了線程池后,再創建一個消息處理器:

 

 

view plaincopy to clipboardprint?private static final InternalHandler sHandler = new InternalHandler(); 

private static final InternalHandler sHandler = new InternalHandler();        注意,這行代碼是在應用程序的主線程中執行的,因此,這個消息處理器sHandler內部引用的消息循環對象looper是應用程序主線程的消息循環對 象,消息處理器的實現機制具體可以參考前面一篇文章Android應用程序消息處理機制(Looper、Handler)分析。

 

        AsyncTask類的靜態初始化代碼執行完成之后,才開始創建AsyncTask對象,即執行AsyncTask類的構造函數:

 

 

view plaincopy to clipboardprint?public AsyncTask() { 

    mWorker = new WorkerRunnable<Params, Result>() { 

        public Result call() throws Exception { 

            ...... 

            return doInBackground(mParams); 

        } 

    }; 

 

    mFuture = new FutureTask<Result>(mWorker) { 

        @Override 

        protected void done() { 

            Message message; 

            Result result = null; 

 

            try { 

                result = get(); 

            } catch (InterruptedException e) { 

                android.util.Log.w(LOG_TAG, e); 

            } catch (ExecutionException e) { 

                throw new RuntimeException("An error occured while executing doInBackground()", 

                    e.getCause()); 

            } catch (CancellationException e) { 

                message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, 

                    new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null)); 

                message.sendToTarget(); 

                return; 

            } catch (Throwable t) { 

                throw new RuntimeException("An error occured while executing " 

                    + "doInBackground()", t); 

            } 

 

            message = sHandler.obtainMessage(MESSAGE_POST_RESULT, 

                new AsyncTaskResult<Result>(AsyncTask.this, result)); 

            message.sendToTarget(); 

        } 

    }; 

public AsyncTask() {

mWorker = new WorkerRunnable<Params, Result>() {

public Result call() throws Exception {

......

return doInBackground(mParams);

}

};

 

mFuture = new FutureTask<Result>(mWorker) {

@Override

protected void done() {

Message message;

Result result = null;

 

try {

result = get();

} catch (InterruptedException e) {

android.util.Log.w(LOG_TAG, e);

} catch (ExecutionException e) {

throw new RuntimeException("An error occured while executing doInBackground()",

e.getCause());

} catch (CancellationException e) {

message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,

new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));

message.sendToTarget();

return;

} catch (Throwable t) {

throw new RuntimeException("An error occured while executing "

+ "doInBackground()", t);

}

 

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

new AsyncTaskResult<Result>(AsyncTask.this, result));

message.sendToTarget();

}

};

}        在AsyncTask類的構造函數里面,主要是創建了兩個對象,分別是一個WorkerRunnable對象mWorker和一個FutureTask對象mFuture。

 

        WorkerRunnable類實現了Runnable接口,此外,它的內部成員變量mParams用于保存從AsyncTask對象的execute函數傳進來的參數列表:

 

 

view plaincopy to clipboardprint?private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { 

    Params[] mParams; 

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {

Params[] mParams;

}        FutureTask類也實現了Runnable接口,所以它可以作為一個工作任務通過調用AsyncTask類的execute函數添加到sExecuto線程池中去:

 

 

view plaincopy to clipboardprint?public final AsyncTask<Params, Progress, Result> execute(Params... params) { 

    ...... 

 

    mWorker.mParams = params; 

    sExecutor.execute(mFuture); 

 

    return this; 

public final AsyncTask<Params, Progress, Result> execute(Params... params) {

......

 

mWorker.mParams = params;

sExecutor.execute(mFuture);

 

return this;

}

 

       這里的FutureTask對象mFuture是用來封裝前面的WorkerRunnable對象mWorker。當mFuture加入到線程池中執行時,它調用的是mWorker對象的call函數:

 

 

view plaincopy to clipboardprint?mWorker = new WorkerRunnable<Params, Result>() { 

    public Result call() throws Exception { 

           ...... 

           return doInBackground(mParams); 

        } 

}; 

mWorker = new WorkerRunnable<Params, Result>() {

public Result call() throws Exception {

       ......

       return doInBackground(mParams);

        }

};        在call函數里面,會調用AsyncTask類的doInBackground函數來執行真正的任務,這個函數是要由AsyncTask的子類來實現的,注意,這個函數是在應用程序的子線程中執行的,它不可以操作應用程序的界面。

 

 

        我們可以通過mFuture對象來操作當前執行的任務,例如查詢當前任務的狀態,它是正在執行中,還是完成了,還是被取消了,如果是完成了,還可以通過它獲得任務的執行結果,如果還沒有完成,可以取消任務的執行。

 

        當工作任務mWorker執行完成的時候,mFuture對象中的done函數就會被被調用,根據任務的完成狀況,執行相應的操作,例如,如果是因為異常 而完成時,就會拋異常,如果是正常完成,就會把任務執行結果封裝成一個AsyncTaskResult對象:

 

 

view plaincopy to clipboardprint?private static class AsyncTaskResult<Data> { 

    final AsyncTask mTask; 

    final Data[] mData; 

 

    AsyncTaskResult(AsyncTask task, Data... data) { 

        mTask = task; 

        mData = data; 

    } 

private static class AsyncTaskResult<Data> {

final AsyncTask mTask;

final Data[] mData;

 

AsyncTaskResult(AsyncTask task, Data... data) {

mTask = task;

mData = data;

}

}        其中,成員變量mData保存的是任務執行結果,而成員變量mTask指向前面我們創建的AsyncTask對象。

        最后把這個AsyncTaskResult對象封裝成一個消息,并且通過消息處理器sHandler加入到應用程序主線程的消息隊列中:

 

 

view plaincopy to clipboardprint?message = sHandler.obtainMessage(MESSAGE_POST_RESULT, 

    new AsyncTaskResult<Result>(AsyncTask.this, result)); 

message.sendToTarget(); 

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

new AsyncTaskResult<Result>(AsyncTask.this, result));

message.sendToTarget();        這個消息最終就會在InternalHandler類的handleMessage函數中處理了:

 

 

view plaincopy to clipboardprint?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; 

        ...... 

        } 

    } 

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;

......

}

}

}        在這個函數里面,最終會調用前面創建的這個AsyncTask對象的finish函數來進一步處理:

 

 

view plaincopy to clipboardprint?private void finish(Result result) { 

       ...... 

       onPostExecute(result); 

       ...... 

private void finish(Result result) {

       ......

       onPostExecute(result);

       ......

}        這個函數調用AsyncTask類的onPostExecute函數來進一步處理,AsyncTask類的onPostExecute函數一般是要由其子類來重載的,注意,這個函數是在應用程序的主線程中執行的,因此,它可以操作應用程序的界面。

        在任務執行的過程當中,即執行doInBackground函數時候,可能通過調用publishProgress函數來將中間結果封裝成一個消息發送到應用程序主線程中的消息隊列中去:

 

 

view plaincopy to clipboardprint?protected final void publishProgress(Progress... values) { 

    sHandler.obtainMessage(MESSAGE_POST_PROGRESS, 

        new AsyncTaskResult<Progress>(this, values)).sendToTarget(); 

protected final void publishProgress(Progress... values) {

sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

new AsyncTaskResult<Progress>(this, values)).sendToTarget();

}        這個消息最終也是由InternalHandler類的handleMessage函數來處理的:

 

 

 

view plaincopy to clipboardprint?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_PROGRESS: 

                 result.mTask.onProgressUpdate(result.mData); 

                 break; 

        ...... 

        } 

    } 

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_PROGRESS:

     result.mTask.onProgressUpdate(result.mData);

     break;

......

}

}

}        這里它調用前面創建的AsyncTask對象的onPorgressUpdate函數來進一步處理,這個函數一般是由AsyncTask的子類來實現的, 注意,這個函數是在應用程序的主線程中執行的,因此,它和前面的onPostExecute函數一樣,可以操作應用程序的界面。

 

       這樣,AsyncTask類的主要實現就介紹完了,結合前面開發的應用程序Counter來分析,會更好地理解它的實現原理。

 

       至此,Android應用程序線程消息循環模型就分析完成了,理解它有利于我們在開發Android應用程序時,能夠充分利用多線程的并發性來提高應用程序的性能以及獲得良好的用戶體驗。 

posted on 2012-03-12 23:33 小果子 閱讀(1841) 評論(0)  編輯 收藏 引用 所屬分類: Android & Ios
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲伦理在线观看| 模特精品裸拍一区| 欧美不卡福利| 欧美国产日韩视频| 一区二区三区av| 亚洲国产裸拍裸体视频在线观看乱了中文| 99视频精品全国免费| 影音先锋亚洲精品| 在线看片成人| 亚洲精品国产精品久久清纯直播| 1769国产精品| 日韩视频在线免费观看| 亚洲色图在线视频| 久久爱另类一区二区小说| 欧美呦呦网站| 久久久夜精品| 亚洲乱码国产乱码精品精可以看 | 亚洲欧美日韩综合国产aⅴ| 欧美亚洲在线播放| 免费成人在线视频网站| 亚洲欧洲一级| 香蕉久久精品日日躁夜夜躁| 免费在线观看精品| 国产精品一二三四| 亚洲一区二区综合| 久久亚洲欧洲| 国产亚洲一区二区精品| 99视频精品免费观看| 久久久免费观看视频| 99re成人精品视频| 欧美a级一区| 尤物视频一区二区| 久久久久**毛片大全| 亚洲一区二区三区777| 欧美成人有码| 亚洲美女少妇无套啪啪呻吟| 女生裸体视频一区二区三区| 中文在线一区| 国产精品成人播放| 午夜精品久久久久久久白皮肤| 亚洲日本va午夜在线电影| 裸体歌舞表演一区二区| 一区二区三区自拍| 免费观看久久久4p| 欧美大秀在线观看| 欧美日韩精品综合在线| 欧美一区二区高清在线观看| 国产精品久久久久国产a级| 亚洲一二三区在线| 午夜精品久久久久久99热| 国产日韩视频| 欧美高清影院| 欧美日韩视频在线一区二区| 亚洲欧美日本精品| 开心色5月久久精品| 一区二区三区日韩欧美| 99精品视频免费观看视频| 欧美二区不卡| 欧美一级视频| 免费成人高清| 欧美精品1区| 欧美中文在线免费| 欧美aⅴ一区二区三区视频| 亚洲无线视频| 欧美国内亚洲| 久久资源在线| 国内外成人在线| 在线视频精品一区| 日韩视频中文| 欧美日韩国产亚洲一区| 女人色偷偷aa久久天堂| 国产综合在线视频| 正在播放亚洲一区| 99国产精品视频免费观看| 久久影院午夜片一区| 久久精品理论片| 国产伦精品一区二区三区高清| 91久久视频| 一区二区三区 在线观看视| 欧美sm重口味系列视频在线观看| 久久精品青青大伊人av| 国产噜噜噜噜噜久久久久久久久| 亚洲欧洲精品一区二区三区| 亚洲伦伦在线| 国产精品久久一区主播| 亚洲影院高清在线| 欧美专区在线播放| 亚洲黄色精品| 国产精品xnxxcom| 欧美一区观看| 亚洲第一视频| 午夜视黄欧洲亚洲| 亚洲国产精品999| 欧美三级网页| 久久经典综合| 日韩亚洲国产精品| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲国产mv| 久久精品免费播放| 日韩视频免费观看| 国产日韩久久| 欧美日韩在线免费观看| 一区二区不卡在线视频 午夜欧美不卡'| 99国产精品久久久久久久久久 | 一区二区三区欧美在线| 久久久久久伊人| 亚洲最黄网站| 亚洲精品激情| 精品二区视频| 国产欧美日韩视频一区二区| 欧美电影资源| 欧美国产日本在线| 久久国产色av| 亚洲一区在线观看免费观看电影高清| 免费中文日韩| 欧美不卡福利| 欧美顶级大胆免费视频| 久久久久久久久岛国免费| 欧美亚洲午夜视频在线观看| 一区二区三区成人| 亚洲色诱最新| 欧美一区二区三区在线观看视频| 99国产精品国产精品久久 | 欧美精品尤物在线| 老鸭窝毛片一区二区三区 | 一区二区精品| a91a精品视频在线观看| 亚洲少妇最新在线视频| 午夜精品av| 欧美电影打屁股sp| 亚洲乱亚洲高清| 一级日韩一区在线观看| 亚洲影院色无极综合| 性欧美video另类hd性玩具| 久久久福利视频| 欧美日韩专区在线| 黑人巨大精品欧美黑白配亚洲| 亚洲成人资源| 欧美一级久久久| 欧美96在线丨欧| 亚洲欧美另类在线观看| 久久久xxx| 欧美国产精品人人做人人爱| 亚洲第一在线综合网站| 日韩视频一区二区三区| 一本色道久久综合亚洲91| 亚洲一区二区三区三| 久久嫩草精品久久久久| 亚洲国产综合91精品麻豆| 亚洲自啪免费| 欧美日韩国产成人精品| 国产午夜精品理论片a级大结局| 久久精品亚洲热| 国产欧美一区二区精品仙草咪| 亚洲精品女av网站| 女同一区二区| 欧美一激情一区二区三区| 欧美日韩精品系列| 亚洲综合色噜噜狠狠| 宅男噜噜噜66国产日韩在线观看| 欧美激情视频一区二区三区在线播放 | 午夜在线电影亚洲一区| 欧美精品一线| 在线视频一区二区| 亚洲精品网站在线播放gif| 理论片一区二区在线| 亚洲黄一区二区三区| 亚洲欧洲精品一区二区三区波多野1战4| 欧美日韩精品免费观看视频| 在线观看成人网| 女同性一区二区三区人了人一| 久久综合色综合88| 亚洲毛片在线观看| 亚洲一区精品在线| 国内精品视频一区| 亚洲九九爱视频| 国产日韩欧美一区二区| 美日韩精品视频免费看| 欧美极品色图| 久久久视频精品| 欧美区国产区| 欧美成ee人免费视频| 欧美三级电影网| 欧美mv日韩mv亚洲| 国产欧美日韩一区| 一区二区欧美精品| 亚洲国产欧美不卡在线观看| 亚洲在线第一页| 日韩视频不卡中文| 老司机精品视频网站| 久久九九全国免费精品观看| 欧美日韩精品在线播放| 亚洲国产精品第一区二区| 在线精品国精品国产尤物884a| 亚洲一区在线免费| 欧美一区二区精品在线| 国产精品无码专区在线观看| 亚洲精品日韩激情在线电影| 国内激情久久| 亚洲视频在线免费观看|