关于AsyncTask使用及原理的一些说明

AsyncTask这个类用的比较多,平时做项目时,一般用在文件下载这一块多比较多。其使用起来还算方便,实现根本的原理还是Thread + Handler。这篇文章就来谈谈AsyncTask的基本使用以及其原理实现,同时说说其和Handler的关系。

1、AsyncTask的基本使用

使用AsyncTask都得实现一个AsyncTask的子类,并在其中重载AsyncTask的一些方法(publishProgress不需要重载,也不能重载,这里放在一起讲),下面就来对这些方法做一些介绍。

protected void onPreExecute()

这个方法主要是在异步执行前去执行一些初始化的工作,因为onPreExecute方法实际上是执行在主线程,所以可以在其中执行一些界面操作。

protected abstract Result doInBackground(Params... params)

这个放是一个异步方法了,也就是说它不是在主线程中执行,故不能再其中执行界面操作,但是由于其是异步方法所以一般在方法体内执行一些耗时操作,不如文件下载等。

protected final void publishProgress(Progress... values)

这个方法用来在doInBackground方法的中抛出进度数据,并通过传递Handler消息,将数据传到后面要讲的onProgressUpdate方法中。

protected void onProgressUpdate(Progress... values)

上面说了,这个方法接收来自publishProgress方法传递过来的数据,并且由于通过Handler机制接收的数据,所以onProgressUpdate这个方法实际是在主线程中执行的,所以能在其中进行界面操作,一般我们在这个方法体中操作进度条。

protected void onPostExecute(Result result)

doInBackground方法执行完毕后会调用改方法,并且由于doInBackground也是通过Handler机制给onPostExcute传递数据,所以在这个方法中也可以操作界面。

protected void onCancelled()

protected void onCancelled(Result result)

这两个方法没啥好说的,也就是取消doInBackground的执行,进而阻断整个异步过程。

另外我们看看AsyncTask类的声明

public abstract class AsyncTask<Params, Progress, Result> 

对比这里的泛型参数和以上几个方法的参数,我们很容易知道,

Params是doInBackground接收的参数类型

Progress是publishProgress以及onProgressUpdate两个方法接收的参数类型

Result是onPostExecute以及onCancelled接收的参数类型

2、AsyncTask工作原理说明

第一小节说明了AsyncTask子类需要重载(或者可以重载)的一些方法,当定义好子类后便可通过子类的实例执行execute方法便可以启动任务运行。

execute方法会执行到下面方法中

@MainThread
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;
}

这里是一个主线程,并在其中执行了onPreExecute方法,这就是我们前面说的onPreExecute执行在主线程中的原因。接着会通过一个线程管理器来执行mFuture,这个mFuture是一个Runable子类实例。

mWorker = new WorkerRunnable<Params, Result>() {
    public Result call() throws Exception {
        mTaskInvoked.set(true);

        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        //noinspection unchecked
        Result result = doInBackground(mParams);
        Binder.flushPendingCommands();
        return postResult(result);
    }
};

mFuture = new FutureTask<Result>(mWorker) {
    @Override
    protected void done() {
        try {
            postResultIfNotInvoked(get());
        } catch (InterruptedException e) {
            android.util.Log.w(LOG_TAG, e);
        } catch (ExecutionException e) {
            throw new RuntimeException("An error occurred while executing doInBackground()",
                    e.getCause());
        } catch (CancellationException e) {
            postResultIfNotInvoked(null);
        }
    }
};

而exec.execute(mFuture)方法会执行到FutureTask.run方法,在执行run方法中有以下代码

try {
    result = c.call();
    ran = true;
} catch (Throwable ex) {
    result = null;
    ran = false;
    setException(ex);
}
if (ran)
    set(result);

这个代码中的c.call()方法调用上面mWorker中的call方法,并在其中执行doInBackground并返回result,然后run方法中接着调动set(result)将result值赋给FutureTask.outcome对象。

run方法最终会执行会mFuture的done方法中来,再看done方法里的postResultIfNotInvoked(get())方法这里有个get()方法获取FutureTask.outcome对象(也就是doInBackground方法返回的result值),然后postResultIfNotInvoked方法会执行到以下postResult方法

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

到这里我们看到使用了Handler机制来传递消息了,那么接受消息的Handler呢就是下面这位大哥了

private static class InternalHandler extends Handler {
    public InternalHandler() {
        super(Looper.getMainLooper());
    }

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

它会根据传过来的MESSAGE_POST_RESULT去执行finish方法,我们再跟一下

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

当没有执行cancel操作时,finish方法会执行onPostExecute方法并获取doInBackground传递过来的值。

以上代码我们说清楚了onPreExecute、doInBackground、onPostExecute这几个方法。

接着我们看看当调用publishProgress方法时,执行如下代码

@WorkerThread
protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
}

我们看到这里还是使用了Handler机制,并传MESSAGE_POST_PROGRESS消息,对比上面的Handler,我们知道Handler接受到消息后会执行onProgressUpdate方法。

这里便讲清了publishProgress方法同onProgressUpdate方法之间的关系。

最后,当在执行过程中进行cancel操作时,会在执行上面的finish方法是执行到onCancelled方法中去而不是执行onPostExecute方法。

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

这样就说清了onCancelled方法。

3、参考文献

1、详[解Android中AsyncTask的使用](http://blog.csdn.net/liuhe688/article/details/6532519)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值