深入认识AsyncTask

走向异步处理AsyncTask


1.AysncTask的三个核心

首先我要说的是网上有很多关于AysncTask的文章,这里我就不累赘重复做过多的基本介绍QAQ,所以我就从侧面阐述我对AysncTask的一些认识。

我们都知道Android官方为了让创建异步任务更简单,把Handler和Thread封装成AysncTask。

所谓三核心,就是三个核心方法:

  • doInBackground(Params… params):继承AysncTask必须重写的一个抽象方法,此方法执行在AysncTask维护的一个线程池中,所以可以在这个方法中做一些耗时操作。
  • onProgressUpdate(Progress… values):执行在主线程中,在doInBackground中调用publishProgress时,执行此方法,可以在主线程更新ui。
  • onPostExecute(Result result):执行在主线程,doInBackground结束时调用这个方法。

2.走进AysncTask

AysncTask从execute开始执行:

    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    //execute又会调executeOnExecutor
        return executeOnExecutor(sDefaultExecutor, params);
    }
    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先执行
        onPreExecute();

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

        return this;
    }

忽略复杂的部分,可以知道在execute的时候最先调用的是onPreExecute方法,所以可以在这里面做一些初始化的操作。
看一下,构造方法:

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

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

        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 occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

在构造方法中对mWorker和mFuture 初始化,mFuture会调用mWork的call方法,那么call方法执行在线程池,mWork的call方法执行了doInBackground,那么doInBackground也执行在线程池。

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

Handler处理MESSAGE_POST_RESULT消息执行finish方法

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

在finish方法中会调用onPostExecute,整个工作流程就差不多了。

3.AysncTask的使用思想

一般的我们可以new一个子线程然后通过handler来更新ui,那为什么还用使用AysncTask呢?
想象一台机器,通过Thread和handler就像打开机器内部修改各种零件,这种方法对于整个过程的控制比较精细,通过AysncTask就像坐在控制台指挥机器工作一样,使得异步创建更加简单,代码不会相对臃肿。
但是AysncTask并不适合进行特别耗时的操作,在更新UI特别是大量的itemview的时候也不是很给力。
线程池是异步操作的重要方式,但是自行实现一个线程池并不容易,因为你需要解决死锁,资源分配,wait和notify等复杂问题,因此Android官方为我们封装的AysncTask使我们更容易实现轻量级,简单的自定义异步类。
下面是几点需要注意的:

  1. AysncTask的对象必须在主线程中创建,execute方法必须在ui线程中调用。

  2. 一个AysncTask对象只能执行一次,只能调用一次execute方法,否则报错。

  3. 在Android3.0之后,为避免并发错误AysncTask采用一个线程串行执行任务。

  4. 不能在doInBackground中更新ui,也不要在onPostExecute中大量更新ui。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值