Android总结03_AsyncTask解析
来源:互联网 发布:centos 拼音不出中文 编辑:程序博客网 时间:2024/06/07 00:48
一.简介
AsyncTask作为一个异步操作类,其主要作用是将耗时操作放入子线程中,再将返回的结果传递到UI线程中.
二.方法
AysncTask作为一个抽象类,使用时必须使用继承AsyncTask的类.为了保证能够和UI线程进行交互,其提供了几个主要方法
onPreExecute():UI线程中,为耗时操作做准备工作
doInBackground():异步线程中,进行耗时操作
onPostExecute(Result result):UI线程中,获取参数为doInBackGround返回的值,实现耗时操作执行完的工作
onPublishProgress(Progress.. progress):UI线程中,参数为进度数值,主要作用是表明当前耗时操作进度
onCancel(),onCancel(Result result):UI线程中,表明耗时操作被取消后的执行工作
三.源码分析
AsyncTask作为异步线程操作类,同时还可以通过其五个方法与UI线程进行交互,主要内部使用了线程池进行耗时操作,使用Handler与外部进行交互.
首先,先定义一个类:定义三个泛型,分别为传入数值,进度,以及结果
public abstract class MyAsyncTask<Params,Progress,Result> {
}
然后定义execute()方法
public final MyAsyncTask<Params, Progress, Result> execute(Params... params) {return this.executeOnExecutor(sDefaultExecutor, params);
}
public final MyAsyncTask<Params, Progress, Result> executeOnExecutor(Executor executor, Params... params) {
}
从这可以看出execute方法后仍需要执行executeOnExecutor()方法,只不过在其基础上多了一个Executor类型的参数,
但是会在executeOnExecutor()方法中执行什么内容呢,其实这里就是执行准备工作,然后开始耗时操作了,下面对executorOnExecutor()方法的代码进行补全
public final MyAsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (this.mExecuteInvoked) {
throw new IllegalArgumentException("已经有任务正在执行");
} else {
//设置任务已经开始执行,保证任务在执行过程中只能执行一次
this.mExecuteInvoked = true;
//执行任务的开始准备工作
this.onPreExecutor();
//设置执行线程的参数
this.mWorker.params = params;
//执行耗时操作
exec.execute(mFuture);
return this;
}
}
到这里我们可以看到onPreExecute已经执行了,但是出现了几个未知的参数mExecuteInvoked,mWorkder和mFuture.
mExecuteInvoked的定义如下:
//volatile是用来实现多线程同步变量的,mExecuteInvoked用来标志当前任务是否正在执行
private volatile boolean mExecuteInvoked = false;
下面我们在来看看mWorker是什么
//定义一个实现了Callable接口的抽象类
//Callable和Runnable差不多,只是在以下三点会有所区别:
//1.定义方法名不同,Callable的方法是Call().Runable的方法是run()
//2.Callable可以返回数据,Runable不能够返回数值
//3.Callable本身可以抛出异常,Runnable不可以抛出异常
public abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] params;
}
//在这里会涉及到doInBackGround,由于返回结果仍在子线程中,所以需要通过postResutl方法进行传递
private final WorkerRunnable<Params, Result> mWorker = new WorkerRunnable<Params, Result>() {
@Override
public Result call() throws Exception {
//设置任务开始执行
MyAsyncTask.this.mTaskInvoked.set(true);
//设置为后台线程
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//执行耗时操作
return MyAsyncTask.this.postResult(MyAsyncTask.this.doInBackground(params));
}
};
由于上一步是在子线程中完成,需要与ui线程进行交互,所以在这里出现了至关重要的Handler类型的对象sHandler.以及一个用来携带数据类型AsyncTaskResult的对象
private Result postResult(Result result){
//初始化即将发送的消息
Message message = sHandler.obtainMessage(1, new AsyncTaskResult(this, new Object[]{result}));
//发送
message.sendToTarget();
return result;
}
先来看看AsyncTaskResult的定义
private static class AsyncTaskResult<Data>{//表示当前执行的异步任务
private MyAsyncTask task;
//携带的数据
private Data[] mData;
public AsyncTaskResult(MyAsyncTask task, Data[] mData) {
this.task = task;
this.mData = mData;
}
}
然后再看Handler的定义
private static class InternalHandler extends Handler{
public InternalHandler() {
//获取主线程
super(Looper.getMainLooper());
}
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what){
case 1://完成
result.task.finish(result.mData[0]);
break;
case 2://更新进度
result.task.onProgressUpdate(result.mData);
break;
}
}
}
此时通过以上我们就能够明白,此时是已经从doInBackground->onPostResult->通过Handler->执行finish->onPostExecute()
但是从上面的程序我们发现mWorkder根本没有执行到,那么这个就涉及我们executeOnExecutor里面的变量mFuture
//Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果
private FutureTask<Result> mFuture;
public MyAsyncTask() {
this.mFuture = new FutureTask<Result>(this.mWorker) {
@Override
protected void done() {
try {
MyAsyncTask.this.postResultIfNotInvoked(get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (CancellationException e) {//取消异常
MyAsyncTask.this.postResult(null);
}
}
};
}
private void postResultIfNotInvoked(Result result) {
boolean wasTaskInvoked = this.mTaskInvoked.get();
if (!wasTaskInvoked) {//如果异步任务没有执行,则发送返回结果出去
this.postResult(result);
}
}
//上面主要就是针对耗时操作在子线程中执行的时候完成,取消 时的操作
下面在来仔细看看mWorker是怎么执行的
上面的execute方法想executeOnExecutor()方法传入了一个Executor对象exec,然后执行exec.execute()方法
private Executor sDefaultExecutor = new MyExecutor();
public class MyExecutor implements Executor {
//任务队列
final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
//当前运行的线程
Runnable mActive;
@Override
public void execute(final Runnable r) {
//将线程放到队列结尾
//下面这个方法明确的意思是,第一次执行时,mActive为空,然后寻找到队首的线程就行执行,这以后其就一直有值,而当第一个线程执行完才会执行完第二个线程,虽然是多线程,可是却是一个线程接着一个线程执行的
mTasks.offer(new Runnable() {
@Override
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
}
//以上我们看到每次执行execute方法时,是将其先放入队列结尾,然后执行了scheduleNext()方法
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
mThreadPollExecutor.execute(mActive);
}
}
这里面又出现了一个新的未知参数mThreadPollExecutor,其实就是一个线程池对象,下面就是对齐初始化
//线程池维护线程的最小数量
private static final int CORE_POOL_SIZE = 5;
//线程池维护线程的最大数量
private static final int MAXIMUM_POOL_SIZE = 255;
//线程池维护线程所允许的时间
private static final int ALIVE_TIME = 1;
//线程池所使用的缓冲队列
private BlockingQueue<Runnable> workQuene;
//创建新线程的线程工厂
private ThreadFactory mThreadFactory = new ThreadFactory() {
//创建新线程个数
private AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "MyAsyncTask#" + mCount.getAndIncrement());
}
};
//线程池
private ThreadPoolExecutor mThreadPollExecutor;
public MyExecutor() {
this(CORE_POOL_SIZE);
}
public MyExecutor(int poolSize) {
this.workQuene = new LinkedBlockingDeque<>(10);
mThreadPollExecutor = new ThreadPoolExecutor(poolSize, MAXIMUM_POOL_SIZE, ALIVE_TIME, TimeUnit.SECONDS, workQuene, mThreadFactory);
}
现在再将取消线程的代码贴一下,这个通过取消操作,执行FutureTask的cancel操作,然后执行done方法,再执行postReusltIfNotVoked方法
//任务是否取消
private final AtomicBoolean mCanceled = new AtomicBoolean();
protected void onCancel() {
}
protected void onCancel(Result result) {
this.onCancel();
}
public final boolean isCanceled() {
return this.mCanceled.get();
}
public final void cancel(boolean mayInterruptRunnable) {
this.mCanceled.set(mayInterruptRunnable);
this.mFuture.cancel(mayInterruptRunnable);
}
- Android总结03_AsyncTask解析
- 297_AsyncTask源码解析
- Android开发_AsyncTask作用
- android耗时任务_AsyncTask
- android学习_AsyncTask(异步任务)
- Android项目之异步处理_AsyncTask
- Android JSON解析总结
- Android Json 解析总结
- 005_AsyncTask 翻译学习
- 01_AsyncTask基本使用
- 295_AsyncTask基本使用
- 296_AsyncTask基本信息
- android 数据解析总结(各种解析)
- Android ApiDemos示例解析:总结
- Android解析XML文件总结
- Android Json解析与总结
- Android Json解析与总结
- Android Json解析与总结
- 235. Lowest Common Ancestor of a Binary Search Tree
- Target runtime Apache Tomcat v7.0 is not defined.
- 【object-c基础】@interface,@implementation
- 计算文章中每个词的权重值-信息熵及代码实现
- 机器人操作系统ROS Indigo 入门学习(13)——验证简单的发布者和订阅者
- Android总结03_AsyncTask解析
- box-shadow与filter的drop-shadow
- Junit使用教程(四)
- 搭建Physical Review Letters(PRL)Latex编辑环境
- 机器人操作系统ROS Indigo 入门学习(14)——用C++语言写一个简单的service和client
- WebService客户端
- C++ primer plus笔记整理 01
- 2.Add Two Numbers(medium)[链表处理 大数相加]
- 机器人操作系统ROS Indigo 入门学习(15)——验证简单的service和client