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

猜你喜欢

转载自blog.csdn.net/wen294299195/article/details/50084969
今日推荐