android總結整理----異步加載

  • Date:2015-4-29
  • Tag:android; AsyncTask、異步加載、Thread、handler、message
  • Author:踏雪
  • Email:[email protected]

一、 介紹

當一個Android app啓動同時,也會啓動一個UI主線程,所有的UI操作都必須在這個UI主線程上執行,如果在子線程執行UI操作則會出現奔潰。一些android上耗時的操作,如圖片加載、數據庫訪問、複雜的業務邏輯處理都應該放在子線程中來完成,否則會出現ANR的問題。現在介紹兩種最常用的異步加載方案。分別是AsyncTask和Thread、Handler實現。

二、 AsyncTask實現異步加載

AsyncTask比較適合那種短時的操作,例如就幾秒鐘。如果想要線程長時間運行,最好用Executor、ThreadPoolExecutor或者FutureTask。繼承AsyncTask的子類至少要實現doInBackground方法。

1、AsyncTask基本參數

AsyncTask< Params, Progress, Result >
(1)Params:傳遞給子線程的參數類型,可以是String、Integer等基本數據類型,也可以是類對象。
(2)Progress:進度參數的數據類型
(3)Result:線程返回結果的數據類型

2、AsyncTask基本方法

(1) onPreExecute: 在線程被執行前執行的一些操作,如初始化工作等。
(2) doInBackground:在onPreExecute執行後被調用的函數,上面說的Params參數就是被傳遞到這個函數方法裏。運行結果也是在這裏返回。在這個函數裏,可以調用publishProgress公佈進度情況。
(3) publishProgress:公佈線程執行的進度。
(4) onProgressUpdate:在publishProgress執行後被調用的函數,用於更新進度信息。
(5) onPostExecute:線程執行完後調用該函數,線程執行的結果作爲該函數的參數。
(6) cancle:終止線程的運行。

3、代碼實例

public class MainActivity extends Activity {

    private TextView textView = null;
    private SeekBar seekBar = null;

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

        textView = (TextView)findViewById(R.id.progress_text);
        seekBar = (SeekBar)findViewById(R.id.progress_bar);

        Worker workder = new Worker("wgc", 90);

        new DemoAsyncTask().execute(workder);
    }

    class Worker {
        private String name;
        private int progress;

        public Worker(String name, int progress) {
            this.name = name;
            this.progress = progress;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getProgress() {
            return progress;
        }

        public void setProgress(int progress) {
            this.progress = progress;
        }

    }

    class DemoAsyncTask extends AsyncTask<Worker, Integer, String>{

        @Override
        protected void onPreExecute() {
            Log.v("test", "onPreExecute() is called!");  
            textView.setText("Loading......");
        }

        @Override
        protected String doInBackground(Worker... params) {
            Log.v("test", "doInBackground() is called!");  

            Worker worker = params[0];

            for(int i = 1; i<= worker.getProgress(); i++) {
                publishProgress(i);//每次使用該函數會調用onProgressUpdate來更新UI的進度

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            return "loading finished!";//這個結果將作爲onPostExecute的參數
        }


        @Override
        protected void onProgressUpdate(Integer... values) {
            Log.v("test", "onProgressUpdate() is called!");
            //更新UI的進度
            textView.setText(values[0] + "");
            seekBar.setProgress(values[0]);
            if(values[0] == 60) this.cancel(true);//終止線程的運行
        }

        @Override
        protected void onPostExecute(String result) {
            Log.v("test", "onPostExecute() is called!");
            textView.setText(result);
        }

    }
}

下面是日誌的輸出結果:可以看到onPreExecute是最先被執行的,然後是doInBackground,在doInBackground裏,每一次調用publishProgress都會onProgressUpdate來更新UI。最後就是調用onPostExecute函數。

三、 Thread+handler實現異步加載

public class MainActivity extends Activity {

    private TextView textView = null;
    private SeekBar seekBar = null;

    private Handler handler;

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

        textView = (TextView)findViewById(R.id.progress_text);
        seekBar = (SeekBar)findViewById(R.id.progress_bar);

        //2.Thread+handler實現異步加載
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Bundle data = msg.getData();

                textView.setText(data.getInt("progress") + "");
                seekBar.setProgress(data.getInt("progress"));
            }
        };

        new Thread(){

            public void run() {
                for(int i = 1; i<= 100; i++) {
                    Message msg = handler.obtainMessage();
                    Bundle bundle = new Bundle();
                    bundle.putInt("progress", i);
                    msg.setData(bundle);
                    handler.sendMessage(msg);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }}.start();
        }
}

四、 HandlerThread實現異步加載

public class MainActivity extends Activity {

    private Handler handler1;

    private TextView text;

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

        text = (TextView)findViewById(R.id.text);

        Log.v("thread_id","UI thread: " + Thread.currentThread().getId());

        HandlerThread handlerThread = new HandlerThread("handler_thread");
        handlerThread.start();

        handler1 = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.v("thread_id","Looper thread1: " + getLooper().getThread().getId());
                text.setText(msg.arg1 + "");
            }
        };

        new Thread(){
            public void run() {
                Message msg = new Message();

                msg.arg1 = 1;
                handler1.sendMessage(msg);

            };
        }.start();

    }
}

參考:
http://www.cnblogs.com/codingmyworld/archive/2011/09/12/2174255.html#!comments

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