Android 异步任务 - AsyncTask 理解及示例

    技术2022-07-11  102

    一、AsyncTask 基本概念等

    + 异步任务,属于辅助类Thread、Handler ,旨在启用和轻松使用UI线程。相当于对Thread和Handler进行了封装。 + 适用于短时操作,数秒内最合适。 + 单线程执行,即使多开,其他线程也是等待状态。
    1、优缺点

    优点:

    1. 使用简单 2. 过程可控 3. 可取消执行

    缺点:

    1. 并行运行多个任务需要更新UI时就变得复杂起来。
    2、参数分析
    //泛型参数,可自定义 public abstract class AsyncTask<Params, Progress, Result> {}

    异步任务使用的三种类型如下:

    Params : 即执行时发送给任务的参数类型。即doInBackground()方法中的参数类型。 Progress : 即后台计算过程中发布的进度单位的类型。即publishProgress()和onProgressUpdate()方法中传入的参数类型。 Result : 是背景计算结果的类型。即doInBackground()方法中返回值的类型。

    假设自定义:

    1.第一个泛型参数指定为Void,表示在执行AsyncTask的时候不需要传入参数给后台任务。 2.第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。 3.第三个泛型参数指定为Boolean,则表示使用布尔型数据来反馈执行结果。
    3、其他了解:
    1. 在1.6版本后AsyncTask改为线程池,允许多线程允许 2. 在3.0版本后为避免并行执行导致的错误,任务在单线程运行

    二、方法解析

    1、onPreExecute()

    1.在执行任务之前在UI线程上调用 2.常用于初始化动作,比如进度条显示

    2、必备方法:doInBackground(Params…)

    1.onPreExecute()执行完成后执行 2.执行是在后台线程,用于执行耗时操作 3.可以调用publishProgress(Progress...)方法更新任务进度

    3、publishProgress(Progress…)

    1.后台计算仍在执行时在用户界面中显示任何形式的进度。 2.可用于为进度栏设置动画或在文本字段中显示日志。

    4、必备方法:onPostExecute(Result)

    1.后台计算完成后在UI线程上调用 2.在doInBackground(...)方法执行完毕后才会运行。 3.会传递doInBackground(...)返回的结果并在界面线程中运行

    5、onProgressUpdate(Progress…)

    1.publishProgress(Progress...)调用后,UI线程将调用这个方法 2.比如通过进度条展示

    6、onCancelled(…)

    1.取消线程操作 2.在主线程调用

    7、其他

    1、enum /** * 用于指示任务的状态,每个状态在任务的生命周期内只设置一次。 */ public enum Status { //指示任务尚未执行。 PENDING, //指示任务正在运行。 RUNNING, //指示{@link AsyncTask#onPostExecute}已经完成。 FINISHED, } //获取状态: getStatus() 2、可以通过executeOnExecutor{…}并行执行,但不建议

    三、注意事项

    1.AsyncTask必须在主线程创建 2.execute(Params...) 必须在UI线程上调用 3.不可手动调用:onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...) 4.该任务只能执行一次(如果尝试第二次执行,则将引发异常。) 5.不建议从线程池中并行运行多个任务,因为未定义其操作顺序。

    四、示例

    示例源自于网络与我自己的修改。

    1、加载进度条

    MainActivity.java

    public class MainActivity extends AppCompatActivity { private TextView txtTitle; private ProgressBar pgBar; private Button btnUpdate; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtTitle = (TextView)findViewById(R.id.txttitle); pgBar = (ProgressBar)findViewById(R.id.pgbar); btnUpdate = (Button)findViewById(R.id.btnupdate); btnUpdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MyAsyncTask myTask = new MyAsyncTask(txtTitle, pgBar); myTask.execute(1000); } }); } }

    MyAsyncTask.java

    package com.shenyang.myapplication; import android.os.AsyncTask; import android.widget.ProgressBar; import android.widget.TextView; public class MyAsyncTask extends AsyncTask<Integer, Integer, String> { private TextView txt; private ProgressBar pgBar; public MyAsyncTask(TextView txt, ProgressBar pgbar) { super(); this.txt = txt; this.pgBar = pgbar; } //该方法不运行在UI线程中,主要用于异步操作,通过调用publishProgress()方法 //触发onProgressUpdate对UI进行操作 @Override protected String doInBackground(Integer... params) { DelayOperator dop = new DelayOperator(); int i = 0; for (i = 2; i <= 100; i += 2) { dop.delay(200); publishProgress(i); } return i + params[0].intValue() + ""; } //该方法运行在UI线程中,可对UI控件进行设置 @Override protected void onPreExecute() { txt.setText("开始执行异步线程~~~"); } //在doBackground方法中,每次调用publishProgress方法都会触发该方法 //运行在UI线程中,可对UI控件进行操作 @Override protected void onProgressUpdate(Integer... values) { int value = values[0]; pgBar.setProgress(value); } }

    辅助类:DelayOperator.java

    public class DelayOperator { /** * 延时操作,用来模拟下载 * @param sleepTime 延时多久 */ public void delay(long sleepTime) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } } }

    布局 activity_main.xml

    <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/txttitle" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.022" /> <ProgressBar android:id="@+id/pgbar" android:layout_width="fill_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.052" style="?android:attr/progressBarStyleHorizontal"/> <Button android:id="@+id/btnupdate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="更新progressBar" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.248" /> </androidx.constraintlayout.widget.ConstraintLayout>

    本文纯属自我学习内容,如有不对的地方,感谢指出。

    Processed: 0.011, SQL: 9