美文网首页
AsyncTask异步任务的源码详细解析

AsyncTask异步任务的源码详细解析

作者: CaoMeng | 来源:发表于2017-10-25 22:12 被阅读9次

1、AsyncTask基本使用:

AsyncTask asyncTask=new AsyncTask<Void,Void,Void>() {
            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                //执行完成返回的方法 UI 主线程
            }
            @Override
            protected Void doInBackground(Void... voids) {
                //执行一些耗时操作 链接网络 读取大型的数据库 运行在Thread
                //在此方法中调用publishProgress();,会将进度值更新在onProgressUpdate(Void... values)方法中
                publishProgress();
                return null;
            }
            @Override
            protected void onPreExecute() {
                //一调用就会执行的方法 更新UI 主线程
                super.onPreExecute();
            }
            @Override
            protected void onProgressUpdate(Void... values) {
                super.onProgressUpdate(values);
                //更新在doInBackground()方法中下载的进度;
            }
        };
        asyncTask.execute("www.baidu.com");

2、AsyncTask源码阅读,点击asyncTask.execute("www.baidu.com");中的execute("www.baidu.com")方法进入AsyncTask的源码...

@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

调用AsyncTask内部方法executeOnExecutor(sDefaultExecutor, params);点击进入该方法:

  @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {//初始状态mStatus == Status.PENDING,所以第一次进入该方法时,不会进入if()方法中。再次调用时,根据状态抛出异常。AsyncTask(同一对象)只能运行一次
            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;//更新mStatus 的状态为Running
        onPreExecute();//首先调用了这个方法
        mWorker.mParams = params;//将传进来的参数赋值给 mWorker.mParams,在子线程中药用到
        exec.execute(mFuture);//然后调用接口方法,应为这是个接口,没法往下看,所以在代码中查找mFuture这个变量用到的地方
        return this;
    }
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);
                }
            }
        };

new FutureTask<Result>(mWorker) {};得到mFuture对象,传入一个mWorker对象:

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

下面我们先来看看FutureTask是个什么东西:

public class FutureTask<V> implements RunnableFuture<V> {...}

首先它实现了RunnableFuture<V>接口,RunnableFuture<V>继承Runnable接口,实现run()方法

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

所以在FutureTask<V>查找run()方法

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

在run()方法中,callable就是通过构造方法传进来的mWorker这个参数,result = c.call();

   public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

现在回到mWorker,调用了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;
            }
        };

调用了result = doInBackground(mParams);方法,在finally{}中,调用了postResult(result);将结果发送到主线程。
在AsyncTask中查找MESSAGE_POST_RESULT,发现:调用了finish()方法

 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 class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

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

那么finish()又是什么方法呢?

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

最后通过onPostExecute(result);将结果传到主线程中去,同时将mStatus = Status.FINISHED;变成Status.FINISHED。完成此AsyncTask对象的异步任务。

相关文章

网友评论

      本文标题:AsyncTask异步任务的源码详细解析

      本文链接:https://www.haomeiwen.com/subject/mopcpxtx.html