Koltin进阶-2-源码实现-AsyncTask

目录

1、背景

2、简介

2.1、详解

2.2、使用

3、源码详解

3.1、new AsyncTask()

3.2、execute()

4、手写代码


1、背景

在Android中,除了Thread扮演线程角色以外,还有AsyncTask、HandlerThread、IntentService同样可以担当起异步线程的任务,它们各自有自己的适用场景。

AsyncTask:封装了Handler和线程池,它主要是为了方便开发者在子线程中更新UI;

HandlerThread:简化了我们创建子线程Handler的过程,简化我们线程间消息传递的过程;

IntentService:内部使用了HandlerThread,它相当于一个后台线程,单相对于Thread来说,它继承了四大组件Service,所以它的优先级会高点,不容易被系统杀死。很适合后台下载类似的任务。

2、简介

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行任务的进度和结果传递给主线程,并在主线程中进行更新UI的操作。

AsyncTask内部实现:使用线程池来执行异步任务,然后通过Handler来将异步任务的结果,推送到我们的UI线程。

注意:AysncTask并不适合执行一些特别耗时的操作,对于特别耗时的任务,建议使用线程池。

2.1、详解

AsyncTask是一个抽象的范型类。

Params:表示参数的类型;

Progres:表示后台任务的执行进度的类型;

Result:表示后台任务返回的结果。

Async提供了四个主要的方法。除了doInBackground()方法在异步线程外,其他的三个方法都在主线程中。

2.2、使用

这里我们继承实现了AsyncTask,然后传入1、2、3三个int值,然后在异步线程池中进行相加,并且每次睡眠3秒,最后将和传到我们的UI线程,看最后的输出结果,我们也能看到只有doInBackground()在异步的线程池中执行。其余的方法都在UI线程中。

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

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        log("onPreExecute.准备");
    }

    @Override
    protected String doInBackground(Integer... integers) {

        int add = 0;
        for (Integer i : integers) {
            publishProgress(i);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            add = add + i;
            log("doInBackground.add=" + add);
        }

        String result = "参数之和=" + add;

        return result;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        for (Integer i : values) {
            log("onProgressUpdate.进度:" + i);
        }
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        log("onPostExecute.结果:" + s);
    }


    private void log(String msg) {
        Log.e("Test_AsyncTask",String.format("%tr", new Date()) + ": "
                + Thread.currentThread().getName() + ": " + msg);
    }
}

----------------------调用---------------------------------
   Test_AsyncTask  test =new Test_AsyncTask()
   test.execute(1, 2, 3)

-----------------------结果---------------------------------

3、源码详解

从上面的使用来看,我们运行Test_My_AsyncTask的时候,只需要new出来Test_My_AsyncTask对象,然后执行它的execute()方法。

那么我们首先看一下AsyncTask的构造函数都做了什么操作?

3.1、new AsyncTask()

看下图:

当我们new 一个AsyncTask对象的时候:

1、我们会创建一个主线程的Handler

2、我们的doInBackground()函数会被放在一个类似线程的执行对象Runnable中;

3、然后我们的doInBackground()函数返回的结果会通过Handler发送到主线程中,并且调用onPostExecute()函数。

4、当然到现在,onPostExecute()还没有被执行,因为我们还没有diao

注意:如果你想要了解Callback 和FutureTask,可以进入这个连接了解一下,如果不想了解,可以把它们当成Runnable也行。

3.2、execute()

execute()的执行:

1、会先调用onPreExecute();

2、sDefaultExecutor线程池会执行我们前面类似Runnable的FutureTask对象,这样就会执行doInBackground()方法。

3、而且在sDefaultExecutor线程池中,我们的doInBackground()并没有执行,只是被添加到一个ArrayDeque中,真正执行该任务的是THREAD_POOL_EXECUTOR线程池。

4、这样我们整个流程就算完成了。

注意:从ArrayDeque来看,默认情况,我们的AsyncTask是串行执行的。

4、手写代码

Async类

package com.yobo.yo_android.test_AsyncTask;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;


public abstract class AsyncTask<Params, Progress, Result> {

    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;
    private final Handler mHandler;

    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();

    public AsyncTask() {

        mHandler = new InternalHandler(Looper.getMainLooper());

        mWorker = new WorkerRunnable<Params, Result>() {
            @Override
            public Result call() {

                mTaskInvoked.set(true);

                Result result = doInBackground(mParams);

                postResult(result);

                return result;
            }
        };

        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                super.done();
                try {
                    postResultIfNotInvoked(get());
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

    }

    private void postResultIfNotInvoked(Result result) {
        boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

    private void postResult(Result result) {
        Message message = mHandler.obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<>(this, result));
        message.sendToTarget();
    }

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

    @SafeVarargs
    private final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {

        onPreExecute();

        mWorker.mParams = params;

        exec.execute(mFuture);

        return this;
    }

    private static class InternalHandler extends Handler {
        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 abstract static class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

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

    private void finish(Result result) {
        onPostExecute(result);
    }

    final void publishProgress(Progress... values) {
        mHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<>(this, values))
                .sendToTarget();
    }

    /**
     * 运行在主线程中,doInBackground()之前就会被调用,可以做一些准备操作
     */
    protected void onPreExecute() {
    }

    /**
     * 运行在线程池中,执行异步任务的地方
     */
    protected abstract Result doInBackground(Params... params);

    /**
     * 运行在主线程之中,可以在doInBackground()中调用publishProgress()函数来触发该方法
     */
    protected void onProgressUpdate(Progress... values) {
    }

    /**
     * 运行在主线程之中,doInBackground()返回的Result结果会被推送这里
     */
    protected void onPostExecute(Result result) {

    }

    /**
     * -------------------------线程池的创建------------------------------------------
     */
    private static final Executor sDefaultExecutor = new SerialExecutor();
    private static final Executor THREAD_POOL_EXECUTOR;

    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(128);

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "线程-Yobo-" + mCount.getAndIncrement());
        }
    };
    /**
     * CPU核心数量
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CPU_COUNT - 1,
                CPU_COUNT * 2 + 1, 30, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
        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();
            }
        }

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

}

Test_My_AsyncTask

package com.yobo.yo_android.test_AsyncTask;

import java.util.Date;

import android.util.Log;


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

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        log("onPreExecute.准备");
    }

    @Override
    protected String doInBackground(Integer... integers) {

        int add = 0;
        for (Integer i : integers) {
            publishProgress(i);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            add = add + i;
            log("doInBackground.add=" + add);
        }

        String result = "参数之和=" + add;

        return result;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        for (Integer i : values) {
            log("onProgressUpdate.进度:" + i);
        }
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        log("onPostExecute.结果:" + s);
    }


    private void log(String msg) {
        Log.e("Test_AsyncTask",String.format("%tr", new Date()) + ": "
                + Thread.currentThread().getName() + ": " + msg);
    }
}
原创文章 120 获赞 34 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/105663943
今日推荐