Android实习生 —— 异步处理之AsyncTask

字数 876阅读 152

目录

前言
一、AsyncTask简介。
二、AsyncTask和Handler对比
  1、AsyncTask实现的原理和适用的优缺点
  2、Handler异步实现的原理和适用的优缺点
三、AsyncTask使用方式。
  - AsyncTask定义了三种泛型类型 Params、Progress、Result
  - 一个异步加载数据最少要重写以下这两个方法
  - 有必要的话你还得重写以下这三个方法,但不是必须的
  - 使用AsyncTask类,以下是几条必须遵守的准则
四、AsyncTask小实例。
【附录】
Demo

前言

在【异步处理之Handler】中我们已经了解了关于线程的相关知识,明白为什么要进行异步处理以及使用Handler进行异步处理的方式,今天我们就来了解一下异步处理的另一种方式 —— ** AsyncTask。**

一、AsyncTask简介。

Android应用的主线程(UI 线程)肩负着绘制用户界面和及时响应用户操作的重任,为了避免在主线程中做耗时操作而产生的ANR提示,我们就要把耗时的任务移出主线程,交给工作者线程去做。工作者线程主要有AsyncTaskIntentServiceHandlerThread,它们本质上都是对线程或线程池的封装。

二、AsyncTask和Handler对比

1、AsyncTask实现的原理和适用的优缺点
  • AsyncTask提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

  • 优点:简单快捷 、过程可控。

  • 缺点:

  • 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来。

  • 只是代码上轻量一些,而实际上要比handler更耗资源。

2、Handler异步实现的原理和适用的优缺点
  • 在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message-Looper获取Message并传递给Handler,Handler逐个获取Looper中的Message,并进行UI变更。

  • 优点:结构清晰,功能定义明确,适于处理多个后台任务。

  • 缺点: 在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)。

【总的来说为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。】

三、AsyncTask使用方式。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法。

  • AsyncTask定义了三种泛型类型 Params、Progress、Result
Params :启动任务执行的输入参数,比如HTTP请求的URL。
Progress :后台任务执行的百分比。
Result :后台执行任务最终返回的结果,比如String。
  • 一个异步加载数据最少要重写以下这两个方法
doInBackground(Params…) 
//后台(非主线程)执行比较耗时的操作,注意这里不能直接操作UI。
//doInBackground在执行过程中可以调用publishProgress(Progress…)来更新任务的进度。
onPostExecute(Result)  
//(主线程执行),相当于Handler处理UI的方式,可以使用在doInBackground 得到的结果处理操作UI。
  • 有必要的话你还得重写以下这三个方法,但不是必须的
onProgressUpdate(Progress…)   
//(主线程执行)可以使用进度条显示任务执行的进度。
onPreExecute()        
//(主线程执行)当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled()             
//用户调用取消时,要做的操作。
  • 使用AsyncTask类,以下是几条必须遵守的准则
  • Task的实例必须在UI thread中创建;
  • execute方法必须在UI thread中调用;
  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
  • 该task只能被执行一次,否则多次调用时将会出现异常;

四、AsyncTask小实例。

  • 新建一个MyAsyncTask
public class MyAsyncTask extends AsyncTask<String, Integer, String> {

    private static final String TAG = "ASYNC_TASK";

    //MainActivity的进度条
    ProgressBar myprogressbar = null;
    //MainActivity的文本
    TextView textView = null;
    // MainActivity的上下文
    Context mycontext = null;

    public MyAsyncTask(ProgressBar progressbar, TextView textview, Context context) {
        myprogressbar = progressbar;
        mycontext = context;
        textView = textview;
    }

    //onPreExecute方法用于在执行后台任务前做一些UI操作
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.i(TAG, "onPreExecute() called");
        textView.setText("正在加载...");
        myprogressbar.setProgress(0);
    }

    //doInBackground方法内部执行后台任务,不可在此方法内修改UI
    //params 由UI线程调用execute()方法传入
    //返回的String类型参数被onPostExecute()方法调用。
    @Override
    protected String doInBackground(String... params) {
        Log.i(TAG, "doInBackground(Params... params) called");

        String ret = null;
        /**
         * 通过Begin,End演示多参数传值
         */
        String Begin = params[0];//取出值Begin
        String End = params[1];//取出值End
        Log.i(TAG, "doInBackground" + Begin);
        /**
         * 模拟耗时步骤
         */
        for (int i = 0; i < 10; i++) {
            /**
             * 后台线程向UI线程发布进度状态i
             */
            publishProgress(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Log.i(TAG, "doInBackground" + End);

        ret = "更新完毕";
        return ret;
    }

    //onPostExecute方法用于在执行完后台任务后更新UI,显示结果
    //result为doInBackground()返回的参数
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.i(TAG, "onPostExecute(Result result) called");
        textView.setText(result);
     }

    @Override
    //onProgressUpdate方法用于更新进度信息
    //values为doInBackground()中publishProgress()返回的参数
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        Log.i(TAG, "onProgressUpdate(Progress... progresses) called");
        int progress = myprogressbar.getMax() / 10 * (values[0] + 1);
        myprogressbar.setProgress(progress);
        textView.setText("正在加载..." + progress + "%");
    }

    //onCancelled方法用于在取消执行中的任务时更改UI
    @Override
    protected void onCancelled() {
        Log.i(TAG, "onCancelled() called");
        textView.setText("已被取消");
        myprogressbar.setProgress(0);
    }
}
  • MainActivity
public class MainActivity extends AppCompatActivity {

    private ProgressBar myProgressBar;
    private Button start, cancel;
    private TextView textView;

    private MyAsyncTask mTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        start = (Button) findViewById(R.id.start);
        cancel = (Button) findViewById(R.id.cancel);
        textView = (TextView) findViewById(R.id.tv);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常
                //启动异步任务,并传入"Begin","End"值演示UI线程向后端线程传值的情况
                mTask = new MyAsyncTask(myProgressBar, textView, getApplicationContext());
                mTask.execute("Begin", "End");

                start.setEnabled(false);
                cancel.setEnabled(true);
            }
        });

        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTask.cancel(true);
                start.setEnabled(true);
                cancel.setEnabled(false);
            }
        });

    }
}
  • 效果
    • 点击开始


      点击开始
  • 执行完毕


    执行完毕
  • 打印结果,注意执行顺序


    打印结果,注意执行顺序
  • 执行取消


    取消
  • 打印结果


    打印结果

【附录】

Demo

AsyncTaskDemo


整理作者:汪博
少壮不努力,老大徒悲伤。
本文为Android学习规划打造,如有不好的地方请多多指教。

推荐阅读更多精彩内容