AsyncTask 源码解析二

asynctask.excute() 其实是初始化了一个线程池来执行操作,只是给线程池的实例化提供了一个时机,相当于一个threadpoolutil。

再来看看它的标准使用方法:里面只有doinbackground 是必须要重写的,其他的可以不重写。

  AsyncTask<Void,Void,Void> asyncTask = new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
                return null;
            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
            }

            @Override
            protected void onProgressUpdate(Void... values) {
                super.onProgressUpdate(values);
            }

            @Override
            protected void onCancelled() {
                super.onCancelled();
            }

            @Override
            protected void onCancelled(Void aVoid) {
                super.onCancelled(aVoid);
            }
            
        };

 这里有个问题,是不是必须要在主线程创建asynctask 实例!


    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        this((Looper) null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Handler handler) {
        this(handler != null ? handler.getLooper() : null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Looper callbackLooper) {
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

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

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

前面第一第二个(自上到下)构造方法,都是调用第三个构造方法传looper 参数,其中looper 是可为空的

如果传了空参数或者 传mainlooper 参数 mHandler 就是 mainHandler 否则就创建一个 handler。但是后两个构造方法是@hide 注释的,也就是看不到的,我们没办法使用。只能用无参的构造方法,从上面的代码可以看到不论是否在主线程中创建asynctask 对象,用的都是mainlooper。

实现其实是通过futuretask 来实现的

关于futuretask

A cancellable asynchronous computation. This class provides a base implementation of 
Future, with methods to start and cancel a computation, query to see if the computation 
is complete, and retrieve the result of the computation. The result can only be 
retrieved when the computation has completed; the get methods will block if the 
computation has not yet completed. Once the computation has completed, the computation
 cannot be restarted or cancelled (unless the computation is invoked using 
runAndReset()).
这是一个可以取消的异步计算,该类提供了Future的基本实现,具有启动和取消运算,查询运算是否结束,并且 
 检查返回计算的结果,该结果只能在运行完成之后才能获取到,如果程序没有运行结束,则`get()`将会阻塞。
 程序运行结束之后,无法重新启动或者是取消程序(除非调用`runAndReset`方法)

就是当callable 执行结束之后get()方法会返回callable 的结果,在结束之前会阻塞在那,直到有结果返回的时候。

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

之后会通过handler 将结果回调

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

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

如果取消了就会回调onCancelled 否则会回调 onPostExcute

整体流程:

1.创建asynctask 实例,只能用无参的构造方法,不管在哪个线程调用 最终获取handler 实例用的都是mainlooper

   private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }

所以其实是可以在子线程创建 asynctask 的,asynctask 本质上是futuretask 的封装,然后利用handler 来更新进度,传递结果

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

这里看一看出来也是利用类加载时初始化的线程池来执行fufturetask,之后通过handler 来传递结果。

所以asynctask 其实就是threadpoolutil,如果你需要返回结果就利用 futuretask,不需要就直接执行。 里面没有对线程的检查,虽然注释说只能在主线程调用!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值