Android中的AsyncTask

近期写了一个项目,在前台刷新界面的时候需要操作数据库,进行数据操作,在UI线程更新数据会导致ANR,程序十分卡,因此用了AsyncTask进行后台数据处理。

介绍

AsyncTask是一个用于在后台线程执行异步任务并在主线程更新UI的类。它是在Android API Level 3中引入的,并被广泛使用。

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

public class MyTask extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... params) {
        // 后台执行耗时操作
        return "result";
    }

    @Override
    protected void onPostExecute(String result) {
        // 在UI线程更新UI
    }
}

AsyncTask定义了三个泛型参数:

  • Params:指定异步任务执行时传入的参数类型。
  • Progress:指定异步任务执行过程中用于更新UI的进度的类型。
  • Result:指定异步任务执行完成后返回的结果类型。

在上面的示例中,ParamsVoid,即没有传入参数,ProgressVoid,即没有进度更新,ResultString,即返回一个字符串结果。

基本结构

AsyncTask是一个抽象类,它的实现需要通过继承它并实现其抽象方法来完成。它的定义如下:

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

其中,ParamsProgressResult是泛型参数,分别对应异步任务执行时传入的参数类型、进度更新的类型和返回的结果类型。

AsyncTask定义了一些静态常量,如SERIAL_EXECUTORTHREAD_POOL_EXECUTORDEFAULT_EXECUTOR等。这些常量表示了AsyncTask可以使用的线程池类型,其中SERIAL_EXECUTOR是一个串行线程池,THREAD_POOL_EXECUTOR是一个固定大小的线程池,DEFAULT_EXECUTOR是默认的线程池。

执行流程

AsyncTask的执行流程可以分为以下几个阶段:

  1. onPreExecute():在UI线程中执行,用于在异步任务执行前进行一些准备工作,例如显示进度条等。
  2. doInBackground(Params...):在后台线程中执行,用于执行耗时操作,不可以更新UI。
  3. onProgressUpdate(Progress...):在UI线程中执行,用于更新进度,例如更新进度条等。
  4. onPostExecute(Result):在UI线程中执行,用于执行异步任务完成后的操作,例如更新UI等。
  5. onCancelled():在UI线程中执行,用于在异步任务被取消时执行的操作。

应用

创建一个类继承AsyncTask

 private class DealDataColor extends AsyncTask {

        @Override
        protected Object doInBackground(Object[] objects) {
           //进行数据处理
            return null;
        }
    }

在主线程调用execute方法更新UI

 DealDataColor dealDataColor = new DealDataColor();
 dealDataColor.execute();

源码分析

这里使用的时候会发现,创建后的AsyncTask在execute后就不能再次使用了,那么为什么会这样设计呢?

看看源码:

//这是execute方法的实现
   public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }



//在execute里调用了executeOnExecutor
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

可以看到这里先判断mStatus的值,这个值是一个枚举类里的值

    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }


  private volatile Status mStatus = Status.PENDING;

这个值在初始化刚进来的时候已经被赋予了PENDING,判断值如果是不是PENDING直接就会抛出异常。

execute()executeOnExecutor() 方法的区别在于:

 

execute是固定了线程池执行。里面传入的sDefaultExecutor 是静态的

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

executeOnExecutor里面可以自定义线程池。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值