异步任务(AsyncTask)

1.Android UI组件更新简介

  Android的UI线程主要负责处理用户的按键事件、用户触屏事件及屏幕绘图事件等,因此开发者的其它操作不应该,也不能阻塞UI线程,否则UI界面将会变的停止响应。Android默认约定当UI线程阻塞超过20秒将会引发ANR异常。不要在UI线程中执行一线耗时的操作。

  为了避免UI线程失去响应的问题,Android建议将耗时操作放在新的线程中完成,但是新的线程也可能需要动态更新UI组件:例如需要从网上获取一个页面,然后在TextView中显示,辞职就应该将连接的网络、获取网络数据的操作放在新的线程中,但是获取网络数据以后,新的线程不允许直接更新UI组件。

  为了界面新线程无法更新UI组件问题,Android提供了如下几种解决办法:

    1.使用Handler实现线程之间的通信

    2.Activity.runOnUiThread(Runnable)

    3.View.post(Runable)

    4.View.postDelayed(Runnable,long)

  使用异步新线程更新UI组件时比较简单。

2.Async<>抽象类:

  Params:启动任务执行的输入参数的类型。

  Progress:后台任务完成的进度值的类型

  Result:后台执行任务完成后返回结果的类型。

3.Async子类的使用步骤:

  第一步:创建AsyncTask子类(继承AsyncTask的类),并为三个泛型指定类型。如果某个泛型参数不需要指定类型,可将它指定为void。

  第二步:根据需要,实现AsyncTask的如下方法

  

Result doInBackground(Params... params);//后台线程将要完成的任务,该方法可以调用publishProgress(Progress... values)方法更新任务的执行进度
onProgressUpdate(Progress... values);//更新任务的执行进度后,将会处罚该方法
onPreExecute() //在执行后台耗时操作前被调用,一般用于完成一些初始化的工作,例如显示进度条等
onPostExecute(Result result) //当doInBackground()完成后,系统会自动调用该方法,并将doInBackground()的返回值传给该方法。

  第三步:调用AsyncTask子类的实例的execute(Params... params)开始执行耗时任务。

4.使用异步的规则:

  1.必须在UI线程中创建AsyncTask的实例

  2.必须在UI线程中创建AsyncTask的execute()方法

  3.AsyncTask的onPreExecute()、onPostExecute(Result result)、doInBackground(Params... params)、onProgressUpdate(Progress... values)方法,由Android系统负责调用。

  4.每一个AsyncTask只能被执行一次,多次调用将会引发异常

5.异步任务的示例:

  下载一个网络资源显示在TextView中,布局很简单一个TextView和一个Button按钮,下面是Activity的程序代码:

public class AsyncTaskActivity extends Activity {
     TextView txtHtml ;
    Button btnDownload;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_asynctask);
        txtHtml = (TextView)findViewById(R.id.txtHtml);
        btnDownload = (Button)findViewById(R.id.btnDownload);

        btnDownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    DownTask task = new DownTask(AsyncTaskActivity.this);
                    task.execute(new URL("http://www.ui.cn/"));//http://www.crazyit.org/ethos.php
                }
                catch (Exception e){
                    e.printStackTrace();
                }

            }
        });

    }





    class DownTask extends AsyncTask<URL,Integer,String>{

        ProgressDialog pdialog ;//进度对话框
        int hasRead=0;
        Context mContext;
        public  DownTask(Context ctx){
            mContext = ctx;
        }
        //重写改方法就是后台线程将要完成的任务。(完成实际的下载任务)
        @Override
        protected String doInBackground(URL... params) {
            StringBuilder sb = new StringBuilder();
            try
            {
                //创建URL连接对象
                URLConnection conn = params[0].openConnection();
                //打开conn连接对象的输入流,并将它包装成BufferdReader
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
                String line = null;
                while ((line = br.readLine()) !=null){
                    sb.append(line+"\n");
                    hasRead++;
                    publishProgress(hasRead);
                }
                return  sb.toString();
            }
            catch (Exception e){
                e.printStackTrace();
            }
         return  null;
        }

        //当下载完成后,将下载的代码显示出来
        @Override
        protected void onPostExecute(String s) {
            txtHtml.setText(s);
            pdialog.dismiss();
        }


        //在下载开始的时候显示一个进度条
        @Override
        protected void onPreExecute() {
            pdialog = new ProgressDialog(mContext);
            pdialog.setTitle("任务正在执行中");//设置对话框标题
            pdialog.setMessage("任务正在执行中,敬请等待....");
            pdialog.setCancelable(false);//设置对话框不能用取消按钮
            pdialog.setMax(202);
            pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pdialog.setIndeterminate(false);
            pdialog.show();

        }


        //负责随着下载进度的改变更新进度条的进度值
        @Override
        protected void onProgressUpdate(Integer... values) {
            txtHtml.setText("已经读取了【"+values[0]+"】行!");
            pdialog.setProgress(values[0]);
        }
    }



}
AcitvityCode

结果图片:

  

  

 

posted @ 2015-08-23 15:28  聆听的风声  阅读(301)  评论(0编辑  收藏  举报