📜  asynctask 在 ui 线程片段上运行 (1)

📅  最后修改于: 2023-12-03 14:39:23.327000             🧑  作者: Mango

在 UI 线程片段上运行 AsyncTask

在 Android 应用程序中,我们经常需要在后台执行一些耗时操作,比如网络请求、数据库查询等等。但是,这些操作不能在 UI 线程中执行,否则会引发 ANR(应用程序无响应)错误。为了解决这个问题,Android 提供了 AsyncTask 类,它可以在后台线程执行耗时操作,并在 UI 线程中更新界面。

什么是 AsyncTask

AsyncTask 是 Android 提供的一个抽象类,用于在后台线程中执行耗时操作,并在 UI 线程中更新界面。它比较适合执行一些相对简单的异步任务,比如网络请求、文件读写、数据库查询等等。

AsyncTask 的好处是它允许在后台线程中执行耗时操作,同时在主线程中更新 UI,而不需要我们手动管理线程。这样可以避免一些线程同步的问题,简化代码逻辑。

AsyncTask 的使用

AsyncTask 是一个抽象类,我们需要继承它,并实现其中的几个方法来完成我们的异步任务。下面是 AsyncTask 类的定义:

public abstract class AsyncTask<Params, Progress, Result> { }

其中,Params 是传入后台线程的参数类型;Progress 是异步执行过程中可以更新 UI 的进度信息类型;Result 是异步执行结束后返回的结果类型。

AsyncTask 中包含三个主要的回调方法:

  • doInBackground(Params...):这个方法在后台线程中执行,通常用于执行一些耗时的操作。在这个方法中可以调用 publishProgress() 来将进度信息传递给 onProgressUpdate() 方法。
  • onProgressUpdate(Progress...):这个方法在主线程中执行,用于更新 UI,通常是更新进度条等视图。在 doInBackground() 方法中调用 publishProgress() 可以触发这个方法的执行。
  • onPostExecute(Result):这个方法在主线程中执行,用于处理 doInBackground() 方法返回的结果。通常用于更新 UI 或者将数据保存到本地等操作。

还有一些其他的回调方法,比如 onPreExecute() 和 onCancelled(),它们也可以用来处理异步任务的开启和取消等操作,但在大部分情况下,我们不需要关注它们。

下面是一个简单的 AsyncTask 的例子:

public class MyTask extends AsyncTask<Void, Integer, String> {
    @Override
    protected String doInBackground(Void... params) {
        int count = 0;
        while (count < 100) {
            count++;
            publishProgress(count);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "Done";
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        // 更新进度条
    }

    @Override
    protected void onPostExecute(String result) {
        // 处理结果
    }
}
在 UI 线程片段上运行 AsyncTask

在 Android 应用程序中,我们通常使用 Fragment 来组织 UI 界面。如果我们需要在 Fragment 中执行一个异步任务,可以按照以下步骤进行:

  1. 在 Fragment 的生命周期方法中创建一个 AsyncTask 对象,并在 onDestroy() 方法中取消异步任务,防止内存泄漏。

  2. 在 Fragment 中重写 AsyncTask 方法,并在其中更新界面。

下面是一个简单的示例代码:

public class MyFragment extends Fragment {

    private MyTask mTask;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTask = new MyTask();
        mTask.execute();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mTask != null && !mTask.isCancelled()) {
            mTask.cancel(true);
        }
    }

    private class MyTask extends AsyncTask<Void, Integer, String> {
        @Override
        protected String doInBackground(Void... params) {
            int count = 0;
            while (count < 100) {
                count++;
                publishProgress(count);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return "Done";
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // 更新 UI 视图
        }

        @Override
        protected void onPostExecute(String result) {
            // 处理结果
        }
    }

}

在这个示例中,我们在 MyFragment 的 onCreate() 方法中创建了一个 MyTask 对象,并调用 execute() 方法开启异步任务。在 onDestroy() 方法中,我们取消了异步任务,这里需要注意判断异步任务是否已经执行完毕或者已经被取消,以避免空指针和崩溃等问题。

在 MyTask 中,我们实现了 doInBackground()、onProgressUpdate() 和 onPostExecute() 方法,并在其中更新了 UI 视图和处理了异步任务的结果。

总结

AsyncTask 是 Android 中的一个常用类,它可以帮助我们在后台线程中执行一些耗时操作,并在 UI 线程中更新界面。在 Fragment 中使用 AsyncTask 也比较简单,只需要在生命周期方法中创建并执行异步任务,并在回调方法中更新 UI 视图即可。当然,在实际应用中,我们还需要处理一些异常情况、取消异步任务等问题,以保证应用程序的健壮性和用户体验。