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

作者: 博儿丶 | 来源:发表于2017-04-04 17:52 被阅读51次

    目录

    前言
    一、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学习规划打造,如有不好的地方请多多指教。

    相关文章

      网友评论

      • 78109ccba476:看到博主的努力也是给自己的一个动力 摒弃不好的 我要继续向前看
        博儿丶:@井井阿 谢谢你 忠实粉丝

      本文标题:Android实习生 —— 异步处理之AsyncTask

      本文链接:https://www.haomeiwen.com/subject/mftzottx.html