1. 程式人生 > >Handle與AsyncTask非同步載入資料

Handle與AsyncTask非同步載入資料

Handle通訊的簡單使用

Handle是在不同的執行緒中進行訊息傳遞的一種機制,或者你可以認為是一個能幫你實現這種功能的類。主要用於解決Android中子執行緒無法更新UI的問題,子執行緒將需要更新的資料通過Handle傳遞給UI執行緒,UI執行緒做更新,這樣就實現了子執行緒更新UI執行緒。

注意,本文不會講Handle的實現原理,不會將AsyncTask的機制框架,只是簡單的教你怎麼使用它們,如果你已經掌握了它們是如果使用的,這篇文章對你不會有太多的幫助

建立Handle

想要用Handle就少不了要建立一個Handle。不過需要注意的是,每個UI執行緒,就是那個Activity類,只能建立一個Handle。訊息是由哪個Handle發的,在UI執行緒中就必須要由哪個Handle處理,建立多了會出現找不到訊息的情況。所以,如果不是必須,儘量一個Activity只建立一個Handle。

建立的程式碼如下:注意,該類需要實現一個父類的方法,即handleMessage(),這個方法是你獲得訊息後,需要如何更新UI,是要在該方法內實現的,比如改變一下某個TextView的內容。其中的引數msg,就是你在子執行緒中要傳遞的訊息。
 public Handler mHandle = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            textView.setText((String)msg.obj);
        }
    };  

使用Handle

handle的使用是在子執行緒中使用,這就需要你將建立的handle宣告為全域性變數。而且在只能建立一個,一定不要在子執行緒中再建立一個。這樣傳遞的訊息在主執行緒的handle是不會處理的(就是找不到訊息,怎處理)。

程式碼如下:新的Thread是你的子執行緒,資料的更新等耗時操作都可以放到這裡來,Message是你需要傳送的訊息物件,可以通過new創建出來,也可以通過handle的方法建立,兩者區別不是太大。但是還是建議使用後者。

Message類有兩個常用的屬性,msg.what,是訊息的屬性,確定訊息的類別,比如網路請求,請求成功what = 200,失敗what = 404,這樣,在UI中就可以判斷,是什麼型別的訊息,做分別處理。第二個屬性是msg.obj,看名字就知道是一個Object物件,如果要傳遞複雜的訊息,比如List,等物件,就可以對該屬性賦值,然後在UI執行緒中強轉。就可以使用了。sendMessage(msg)是將訊息傳送出去。

順便說一下,如果你不需要傳送什麼訊息,僅僅是需要通知下UI執行緒,可以使用mHandle.sendEmptyMessage(int what);引數是訊息型別。

程式碼如下

public void changeText(){
     new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = mHandle.obtainMessage();
                msg.what = 3;
                msg.obj = "子執行緒改變";

                mHandle.sendMessage(msg);
            }
        }).start();
}

AsyncTask 簡單使用

AsyncTack是一種非同步載入機制,一般用在ListView,下拉重新整理的ListView,當下拉時,載入的資料可以使用這種機制載入。

Asynctask 的建立

要使用AsyncTask時,需要建立一個類,並繼承AsyncTaskAsyncTask<Params, Progress, Result> 。這個類有幾個方法需要實現,有在後臺載入資料的方法,有在UI中執行更新UI的方法。AsyncTask類有三個泛型,Params是指在後臺執行的操作需要引數時的引數型別。Progress是當前後臺執行的任務,即載入資料的進度,Result是後臺任務執行結束後返回的結果集型別。

繼承該類後需要實現幾個方法,必須要實現一個,根據你需要的功能再實現其他的。

doInBackground() 這個是你必須要實現的方法,用於資料載入等耗時操作,該方法不能訪問UI執行緒。該方法在執行完onPreExecute()方法後執行。

onPreExecute()該方法是在UI執行緒中執行的,一般是在執行doInBackground() 前對UI進行的一些操。不是必須要實現的。

onPostExecute(Result) 該方法是在UI執行緒中執行的,是在執行完doInBackground() 方法後執行的,傳遞的引數是doInBackground() 返回的結果集。

onProgressUpdate(Progress) 方法是在UI中執行的,是將後臺任務的進度更新到UI中,比如更新進度條之類的。

注意:如果需要使用onProgressUpdate() 方法更新進度,就必須在doInBackground()方法中將進度傳遞出去,這就要用到publishProgress(Progress)方法,該方法是將當前進度傳遞出去

忘了說了,如果你不需要這些範型,可以用 Void 代替,對,你沒看錯,是大寫的’V’

程式碼如下:

public class DownLoadTask extends AsyncTask<String, Integer, String> {

        /**
         * 在後臺執行的方法,獲取資源
         * @param params
         * @return
         */
        @Override
        protected String doInBackground(String... params) {

            //在doInBackground對外公佈任務進度,類似sendMessage
            publishProgress(i);
            }
            return "";
        }

        /**
         * 主執行緒在執行doInBackground方法之前執行的方法
         * 該方法在主執行緒中執行
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        /**
         * 主執行緒在執行doInBackground之後執行該方法
         *
         * @param s doInBackground 方法的返回結果
         */
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            textView.setText(s);
        }

        /**
         * 用於接收 publishProgress 公佈的引數執行在主執行緒中
         * @param values publishProgress 的引數
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);

        }
    }

AsyncTask使用

AsyncTask的使用非常簡單,建立你剛剛建立的那個繼承AsyncTask的類物件,然後呼叫 execute(Params)方法即可

程式碼如下:

    DownLoadTask down = new DownLoadTask();
    //如果你的Params是Void就別傳引數了
    down.execute("www.baidu.com");

Handle與AsyncTask 簡單對比

相同點

 Handle與AsyncTask 都是為了解決非同步載入的問題的。用於將子執行緒中載入的資料,傳遞到UI執行緒中。都是為了在不阻塞UI執行緒的同時執行其他執行緒。

Handle

handle使用簡單,在處理多個程序的通訊,多種訊息的處理時優於AsyncTask,容易理解,它是將訊息從子執行緒傳送到UI執行緒中去,在UI執行緒中做處理。是Android中執行緒間通訊的主流使用方法。

AsyncTask

AsyncTask是一種非同步載入的機制,是將資料載入,UI的更新封裝到一個類中,然後將這些介面暴露出來,讓你去實現。理解起來比較不容易,使用時比較簡單,適用與簡單的資料載入,在面對多個執行緒通訊時可能有些不足