AsyncTask - 轻量级的异步任务类

AsyncTast相当于封装了Thread和Handler,它可以在线程池中执行后台任务,然后把执行结果和进度传递回主线程并在主线程更新UI。使用如下:

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyAsyncTask asyncTask = new MyAsyncTask();
        asyncTask.execute("www.baidu.com","www.baidu.com");
    }


    public class MyAsyncTask extends AsyncTask<String,Integer,String>{


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.d(">>>>>>>>", "onPreExecute: 开始执行了");
        }

        @Override
        protected String doInBackground(String... params) {
            int timer = 0;
            for (int i = 0;i<5;i++){
                try {
                    Thread.sleep(1000);
                    publishProgress(timer++);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            return params[0];
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            SimpleDateFormat    sDateFormat    =   new SimpleDateFormat("yyyy-MM-dd    hh:mm:ss");
            Log.d(">>>>>>>>>", "onProgressUpdate: "+sDateFormat.format(new Date())+"休眠1秒传回的值:"+values[0]);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            Log.d(">>>>>>>>", "onPostExecute结果: "+s);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            Log.d(">>>>>>>>>", "onCancelled: called");
        }
    }
}
执行结果:
04-17 10:55:42.913 13451-13451/com.example.androidtext D/>>>>>>>>>: onProgressUpdate: 2017-04-17    10:55:42休眠1秒传回的值:0
04-17 10:55:43.913 13451-13451/com.example.androidtext D/>>>>>>>>>: onProgressUpdate: 2017-04-17    10:55:43休眠1秒传回的值:1
04-17 10:55:41.908 13451-13451/com.example.androidtext D/>>>>>>>>: onPreExecute: 开始执行了
04-17 10:55:44.908 13451-13451/com.example.androidtext D/>>>>>>>>>: onProgressUpdate: 2017-04-17    10:55:44休眠1秒传回的值:2
04-17 10:55:45.913 13451-13451/com.example.androidtext D/>>>>>>>>>: onProgressUpdate: 2017-04-17    10:55:45休眠1秒传回的值:3
04-17 10:55:46.913 13451-13451/com.example.androidtext D/>>>>>>>>>: onProgressUpdate: 2017-04-17    10:55:46休眠1秒传回的值:4
04-17 10:55:46.913 13451-13451/com.example.androidtext D/>>>>>>>>: onPostExecute结果: www.baidu.com

由上可以看出,AsyncTast提供了三个泛型参数:1-Params表示参数的类型,2-Progress表示后台任务进度类型,3-Result表示后天类型结果返回的类型。(如果没有指定参数,可以用Void代替) 5个核心方法:1-onPreExecute()在主线程中调用,在异步线程开始前调用,比如显示网络请求的进度条; 2-doInBackground(String… params)在线程池中执行,用于执行后台任务,其中String为三个泛型参数的Params,在这个方法中可以调用;publishProgress(timer++)方法,给onProgressUpdate(Integer… values)传递进度数据;3-onProgressUpdate(Integer… values)在主线程中执行,其中Integer… values为三个泛型参数的Progress,一般用于进度显示,比如下载数据的进度条;4-onPostExecute(String s)在主线程中调用,一般是doInBackground方法执行完成后返回的结果,其中String s就是三个泛型参数中的Result参数;5-onCancelled()在主线程中调用,用于取消的异步任务。此时就不会调用onPostExecute方法了。
调用AsyncTast的execute方法开始异步任务。其中使用AsyncTast还有几点需要注意:1-AsyncTast的对象必须在主线程中创建;2-execute方法用而不需在主线程UI线程调用;3-一个AsyncTask对象只能执行一次,就是只能调用一次execute方法;4-在3.0之后AsyncTask调用execute方法是串行的,可以调用executeOnExecutor实现并行。
AsyncTast的原理分析
首先从execute方法入手:

@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
    @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;
    }

从上面可见调用AsyncTask的execute方法最终还是会调用executeOnExecutor方法,在顶用executeOnExecutor这个方法传入的是一个默认的串行线程池,在executeOnExecutor方法中首先调用的是onPreExecute()方法;

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
 private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

从上可以看出是AsyncTask是串行的,其中在AsyncTask的构造器中会初始化WorkerRunnable和FutureTask,吧传入的Params值附给WorkerRunnable的mParams,FutureTask是一个并发类,充当Runnble的作用,之后就会交给SerialExecutor 的execute处理。处理结果会回调会WorkerRunnable的call()方法,

mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };

可以看出在执行SerialExecutor 的execute方法时候,会调用FutureTask的run()方法,由此而触发WorkerRunnable的call()方法,在call()方法里面调用AsyncTask的doInBackground(mParams)方法,所以doInBackground方法是在线程池中执行的,执行完doInBackground方法返回值后又走postResult(result)方法切换到主线程:

private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
    private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }
 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;
            }
        }
    }
@SuppressWarnings({"RawUseOfParameterizedType"})
    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

上面的创建一个Handler(InternalHandler )实列,InternalHandler 用Looper.getMainLooper()的方法创建了一个主线程的Hander实列。后把结果封装到AsyncTaskResult类里面,Handler切换回主线程,调用AsyncTask的onPostExecute()方法,所以onPostExecute执行在主线程。AsyncTask的使用以及部分源码的说明。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值