异步任务的实现(AsyncTask)

版权声明:转载请申明出处,谢谢 https://blog.csdn.net/qq_35495763/article/details/87858828

update time:2019-2-21 author:要你命三千又三千 type:学习笔记

概念的简介

AsyncTask 是一个轻量级的异步任务类,是由谷歌提供的使用简单。

异步:异步对应于同步任务
同步任务是单线程的,顺序执行的任务,而异步对应于多线程的任务执行方式。(通俗理解同步任务就是顺序执行的任务,而异步任务就是在多个线程中执行的任务,异步任务之间一般需要通信)

因为Android程序刚启动时,会同时启动一个对应的主线程(Main Thread),这个主线程主要负责处理 与UI相关的事件!有时我们也把他称作UI线程!而在Android App时我们必须遵守这个单线程模型的规则: Android UI操作并不是线程安全的并且这些操作都需要在UI线程中执行! 假如我们在非UI线程中,比如在主线程中new Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views 。 另外,还有一点,如果我们把耗时的操作都放在UI线程中的话,如果UI线程超过5s没有响应用于请求,那么 这个时候会引发ANR(Application Not Responding)异常,就是应用无响应~ 最后还有一点就是:Android 4.0后禁止在UI线程中执行网络操作~不然会报: android.os.NetworkOnMainThreadException

以上的种种原因都说明了Android引入异步任务的意义,当然实现异步也不可以不用到我们本节讲解 的AsyncTask,我们可以自己开辟一个线程,完成相关操作后,通过下述两种方法进行UI更新:

  • 前面我们学的Handler,我们在Handler里写好UI更新,然后sendMessage()等的方法通知UI 更新,Handler写在主线程和子线程中是有区别的
  • 利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,更新UI时,把Runnable 对象传进来即可

实现简单的AsyncTask的实现

  • 创建 AsyncTask 子类 & 根据需求实现核心方法
  • 创建 AsyncTask子类的实例对象(即 任务实例)
  • 手动调用execute()从而执行异步线程任务

在这里插入图片描述

AsyncTask的三个泛型参数说明(三个参数可以是任何类型)

class BitmapWorkTask extends AsyncTask<Integer,Integer,Bitmap>{…}

  • 第一个参数:传入doInBackground()方法的参数类型 对应的execute()传入的参数
  • 第二个参数:传入onProgressUpdate()方法的参数类型
  • 第三个参数:传入onPostExecute()方法的参数类型,也doInBackground()方法返回的类型
        @Override
        protected Bitmap doInBackground(Integer... integers) {
            data = integers[0];
            return decodeSampleBitmapFromResources(getResources(),data,100,100);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (weakReference != null && bitmap != null) {
                final ImageView imageView = (ImageView) weakReference.get();
                if (imageView != null) {
                    imageView.setImageBitmap(bitmap);
                }
            }
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

使用实例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
   >
    <Button
        android:layout_centerInParent="true"
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点我加载"/>
    <TextView
        android:id="@+id/text"
        android:layout_below="@+id/button"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="还没开始加载!" />
    <ProgressBar
        android:layout_below="@+id/text"
        android:id="@+id/progress_bar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:max="100"
        style="?android:attr/progressBarStyleHorizontal"/>
    <Button
        android:layout_below="@+id/progress_bar"
        android:layout_centerInParent="true"
        android:id="@+id/cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="cancel"/>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
    MyTask mTask;
    Button button,cancel; // 加载、取消按钮
    TextView text; // 更新的UI组件
    ProgressBar progressBar; // 进度条
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        button = findViewById(R.id.button);
        cancel = findViewById(R.id.cancel);
        text = findViewById(R.id.text);
        progressBar = findViewById(R.id.progress_bar);
        mTask = new MyTask();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTask.execute();
            }
        });
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTask.cancel(true);
            }
        });
    }
    private class MyTask extends AsyncTask<String, Integer, String> {

        // 方法1:onPreExecute()
        // 作用:执行线程任务前的操作
        @Override
        protected void onPreExecute() {
            text.setText("加载中");
            // 执行前显示提示
        }


        // 方法2:doInBackground()
        // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
        // 此处通过计算从而模拟“加载进度”的情况
        //在子线程中运行
        @Override
        protected String doInBackground(String... params) {

            try {
                int count = 0;
                int length = 1;
                while (count<99) {

                    count += length;
                    // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
                    publishProgress(count); //此方法自动调用onProgressUpdate()来执行
                    // 模拟耗时任务
                    Thread.sleep(50);
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        // 方法3:onProgressUpdate()
        // 作用:在主线程显示线程任务执行的进度
        @Override
        protected void onProgressUpdate(Integer... progresses) {
            progressBar.setProgress(progresses[0]);
            text.setText("loading..." + progresses[0] + "%");
        }

        // 方法4:onPostExecute()
        // 作用:接收线程任务执行结果、将执行结果显示到UI组件
        @Override
        protected void onPostExecute(String result) {
            // 执行完毕后,则更新UI
            text.setText("加载完毕");
        }
        // 方法5:onCancelled()
        // 作用:将异步任务设置为:取消状态
        //当调用cancel()系统会调用onCancelled()方法。
        @Override
        protected void onCancelled() {
            text.setText("已取消");
            progressBar.setProgress(0);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35495763/article/details/87858828