AsyncTask了解
使用
var task: MyAsynacTask? = null
task = MyAsynacTask()
task?.execute()// 开启任务
// 只能执行一次&必须在UI线程调用
// task?.execute()
task?.cancel(true)// 手动取消
var tag: String = "MyAsynacTask_"
final inner class MyAsynacTask : AsyncTask<String, Int, String>() {
override fun onPreExecute() {
super.onPreExecute()
Log.e(tag, "onPreExecute 下载之前")
AsynacText.text = "下载之前"
}
override fun doInBackground(vararg params: String?): String {
Log.e(tag, "doInBackground")
var num: Int = 0
while (num < 99) {
num += 2
publishProgress(num)
Thread.sleep(30)
}
return ""
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
Log.e(tag, "onProgressUpdate 更新中")
progressbar.setProgress(values[0]!!)
AsynacText.text = "${values[0]!!} %"
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
Log.e(tag, "onPostExecute $result")
AsynacText.text = "执行完毕"
}
override fun onCancelled() {
super.onCancelled()
Log.e(tag, "onCancelled")
AsynacText.setText("已取消")
progressbar.setProgress(0)
}
override fun onCancelled(result: String?) {
super.onCancelled(result)
Log.e(tag, "onCancelled result:")
}
}
布局样式
两个btn & 一个ProgressBar & 一个Textview
注意事项:
- 只能执行一次
- 必须在UI线程调用
这里不在演示动图!
效果图:
1. 默认下载完毕:执行相关方法
2. 下载途中手动取消下载
源码分析
源码思维导图
核心颜色说明
以下是思维导图中的核心颜色区分:
- 紫色
必须重写 & 可重写的 & 手动调用 的核心方法,我们使用AsyncTask会用到这些回调方法 - 红色
源码中执行 的核心方法 - 绿色
手动调用execute,是如何添加到任务队列 的核心方法
具体分析
下面源码分析中,标题也会按照核心颜色去设置!
思维方向:
- 熟悉上图
AsyncTask了解
部分的概念、和必须重写 & 可重写 & 手动调用
的方法。最好先会怎么使用 - 看源码
AsyncTask的构造方法
做了哪些事情,可以先跟着看一遍,知道怎样的一个流程,熟悉这个流程中用到了哪些方法、哪些类(这里可以不用非要揪着某个函数死磕) - 在从主动调用的方法
execute()
跟踪查看源码做了什么,即思维导图中的:主动调用
- 最后查看获取AsyncTask实例时,内部的默认初始化做了哪些操作。即思维导图中的:
获取AsyncTask实例时的初始化配置
- 做完上面的操作,在去看任务是如何添加到线程池队列中的。即思维导图中的绿色代码
- 看完这些,再结合上图的思维导图,进行综合的理解。 或者跟着思维导图先熟悉也可。
注:我看源码时,边看边在笔记本上花草图,算是比较笨的方法吧
AsyncTask构造方法
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 {
//1. 设置调用标识
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
// 2. 执行异步操作。即使用AsyncTask 必须重写的执行异步操作
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
// catch 设置取消标识
mCancelled.set(true);
throw tr;
} finally {
// 3. 获取Handler 对象,发送消息 分析->postResult
postResult(result);
}
return result;
}
};
//用来包装Callable对象
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
// 复查任务的调用 分析->postResultIfNotInvoked
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);
}
}
};
}
- 分析->postResult
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
- 分析->postResultIfNotInvoked
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result); //分析->postResult
}
}
主动调用
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
// .... 省略N行代码
// 1.设置Status为RUNNING状态
mStatus = Status.RUNNING;
//2. 任务开始之前回调该方法
onPreExecute();
// 3.赋值
mWorker.mParams = params;
// 4.将任务添加到线程池中 exec请看下面分析:获取AsyncTask实例时的初始化配置
exec.execute(mFuture);
return this;
}
获取AsyncTask实例时的初始化配置
- SerialExecutor
private static class SerialExecutor implements Executor {
// 1. 维护一个双向队列:ArrayDeque 没有容量限制,可根据需求自动进行扩容。
//ArrayDeque不支持值为 null 的元素。
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
//2. exec.execute(mFuture); 调用时,将mFuture传入=添加一个新任务
//synchronized同步锁,保证串行执行
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 3. mActive == null时调用 scheduleNext();去队列中取出1任务个执行
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//4. mActive = mTasks.poll() 取出队列头部任务
if ((mActive = mTasks.poll()) != null) {
//5. 执行即耗时任务 关于 THREAD_POOL_EXECUTOR请看下面 ThreadPoolExecutor:用于并行执行任务的线程池 分析
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
- ThreadPoolExecutor:用于并行执行任务的线程池
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors()
//2.设置线程池的最大线程数为 CPU核数*2+1
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//2.设置线程池的最大线程数为 CPU核数*2+1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 3.线程池空闲线程存活时间30s
private static final int KEEP_ALIVE_SECONDS = 30;
//4. TimeUnit.SECONDS
// 6.初始化线程工厂
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//5.初始化存储任务的队列为LinkedBlockingQueue 最大容量为128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
- 初始化一个Handler(静态内部类:InternalHandler)
总结
到这里分析完结。
本文主要是分模块去分析的,最后可以串联起来:具体看思维导图
- AsyncTask构造方法模块
- handler发送消息模块(postResult)
- 主动调用模块
- 获取AsyncTask实例时的初始化配置模块
上述:
1-2跟踪AsyncTask构造方法源码查看时,最终跟踪到Handler模块
3最后核心方法 *exec.execute(mFuture); 将mFuture传入=添加一个新任务
4最后会调用 THREAD_POOL_EXECUTOR.execute(mActive);执行耗时任务,即TAsyncTask构造方法中的new WorkerRunnable,重写的call方法中
感谢观看!如有什么不正确的,麻烦大佬指出。谢谢!
搞了将近两天,主要根据源码画思维导图这一块花的时间久点,大佬不妨点个赞吧。