当前位置: 代码迷 >> 综合 >> Koltin进阶-2-源码实现-AsyncTask
  详细解决方案

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

热度:49   发布时间:2023-10-09 04:43:11.0

目录

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、详解

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

AsyncTask是一个抽象的范型类。

Params:表示参数的类型;

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

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

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

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

2.2、使用

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

public class Test_My_AsyncTask extends AsyncTask<Integer, Integer, String> {@Overrideprotected void onPreExecute() {super.onPreExecute();log("onPreExecute.准备");}@Overrideprotected 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;}@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);for (Integer i : values) {log("onProgressUpdate.进度:" + i);}}@Overrideprotected 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)-----------------------结果---------------------------------

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

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也行。

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

3.2、execute()

execute()的执行:

1、会先调用onPreExecute();

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

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

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

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

Koltin进阶-2-源码实现-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>() {@Overridepublic Result call() {mTaskInvoked.set(true);Result result = doInBackground(mParams);postResult(result);return result;}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected 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();}@SafeVarargspublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}@SafeVarargsprivate 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" })@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.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;@SafeVarargsAsyncTaskResult(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> {@Overrideprotected void onPreExecute() {super.onPreExecute();log("onPreExecute.准备");}@Overrideprotected 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;}@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);for (Integer i : values) {log("onProgressUpdate.进度:" + i);}}@Overrideprotected 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);}
}