AsyncTask源码解析
package com.example.demo.activity.net; import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
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.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.Process; public abstract class MyAsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
// 返回cpu的数目
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 设置核心线程数量
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
// 设置最大线程数量
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 设置活跃时间
private static final int KEEP_ALIVE = 1;
// 创建线程的工厂
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());
}
}; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); // 创建了一个线程池,传入参数为核心线程2,最多线程3,休息时间1秒,容纳128个线程对象的队列,线程工厂
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
// 创建一个串行执行任务对象
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
// handler接受码
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
// handler对象
private static final InternalHandler sHandler = new InternalHandler();
// 默认使用串行执行
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
// 继承了一个泛型的回掉接口,在mFuture的run方法中会调用mWorker的call回调方法
private final WorkerRunnable<Params, Result> mWorker;
// 线程对象,实现了RunnableFuture接口
private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING;
// 判断是否已经主动取消执行中的任务
private final AtomicBoolean mCancelled = new AtomicBoolean();
// 判断
private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); // 判断是否正常调用postResult(doInBackground(mParams))
private static class SerialExecutor implements Executor {
// 维护的队列,每execute一次就offer进来一个mFuture线程对象
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive; public synchronized void execute(final Runnable r) {
// 默认的execute提交就是把封装的mFuture用该方法提交,所有提交的线程对象都先存放在该队列中
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 队列中所有线程对象都执行完之后,mActive = mTasks.poll()就会等于null
// 然后新加入的任务又会重新启动执行
if (mActive == null) {
scheduleNext();
}
} // 从队列中获取一个线程对象,将他放到线程池中执行,执行完之后就会接着调用scheduleNext()来执行队列中的下一个线程对象
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
} /**
* Indicates the current status of the task. Each status will be set only once during the lifetime of a task.
*/
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
} /** @hide Used to force static handler to be created. */
public static void init() {
sHandler.getLooper();
} /**
* 设置默认的线程池
*
* @param exec
*/
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
} /**
* 构造函数,初始化了mFuture线程对象,并封装了mWorker回调接口
*/
public MyAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true); Process.setThreadPriority(10);
// noinspection unchecked
return postResult(doInBackground(mParams));
}
};
// 被强行打断,出异常,或者正常结束都会调用下面的done(),
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 occured while executing doInBackground()", e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
} // 正常结束,出异常,被强行打断就会调用下面的方法
// 但是正常结束不会调用里面的postResult(result)。因为他已经在call()中调用
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
} /**
* 使用handler往主线程中发送返回结果
*
* @param result
* @return
*/
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
} /**
* Returns the current status of this task.
*
* @return The current status.
*/
public final Status getStatus() {
return mStatus;
} /**
* Override this method to perform a computation on a background thread. The specified parameters are the parameters passed to {@link #execute} by the caller of this task.
*
* This method can call {@link #publishProgress} to publish updates on the UI thread.
*
* @param params
* The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
protected abstract Result doInBackground(Params... params); /**
* Runs on the UI thread before {@link #doInBackground}.
*
* @see #onPostExecute
* @see #doInBackground
*/
protected void onPreExecute() {
} /**
* <p>
* Runs on the UI thread after {@link #doInBackground}. The specified result is the value returned by {@link #doInBackground}.
* </p>
*
* <p>
* This method won't be invoked if the task was cancelled.
* </p>
*
* @param result
* The result of the operation computed by {@link #doInBackground}.
*
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@SuppressWarnings({ "UnusedDeclaration" })
protected void onPostExecute(Result result) {
} /**
* Runs on the UI thread after {@link #publishProgress} is invoked. The specified values are the values passed to {@link #publishProgress}.
*
* @param values
* The values indicating progress.
*
* @see #publishProgress
* @see #doInBackground
*/
@SuppressWarnings({ "UnusedDeclaration" })
protected void onProgressUpdate(Progress... values) {
} /**
* <p>
* Runs on the UI thread after {@link #cancel(boolean)} is invoked and {@link #doInBackground(Object[])} has finished.
* </p>
*
* <p>
* The default implementation simply invokes {@link #onCancelled()} and ignores the result. If you write your own implementation, do not call <code>super.onCancelled(result)</code>.
* </p>
*
* @param result
* The result, if any, computed in {@link #doInBackground(Object[])}, can be null
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
@SuppressWarnings({ "UnusedParameters" })
protected void onCancelled(Result result) {
onCancelled();
} /**
* <p>
* Applications should preferably override {@link #onCancelled(Object)}. This method is invoked by the default implementation of {@link #onCancelled(Object)}.
* </p>
*
* <p>
* Runs on the UI thread after {@link #cancel(boolean)} is invoked and {@link #doInBackground(Object[])} has finished.
* </p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled() {
} /**
* Returns <tt>true</tt> if this task was cancelled before it completed normally. If you are calling {@link #cancel(boolean)} on the task, the value returned by this method should be checked
* periodically from {@link #doInBackground(Object[])} to end the task as soon as possible.
*
* @return <tt>true</tt> if task was cancelled before it completed
*
* @see #cancel(boolean)
*/
public final boolean isCancelled() {
return mCancelled.get();
} /**
* <p>
* Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and
* this task has not started when <tt>cancel</tt> is called, this task should never run. If the task has already started, then the <tt>mayInterruptIfRunning</tt> parameter determines whether the
* thread executing this task should be interrupted in an attempt to stop the task.
* </p>
*
* <p>
* Calling this method will result in {@link #onCancelled(Object)} being invoked on the UI thread after {@link #doInBackground(Object[])} returns. Calling this method guarantees that
* {@link #onPostExecute(Object)} is never invoked. After invoking this method, you should check the value returned by {@link #isCancelled()} periodically from {@link #doInBackground(Object[])} to
* finish the task as early as possible.
* </p>
*
* @param mayInterruptIfRunning
* <tt>true</tt> if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.
*
* @return <tt>false</tt> if the task could not be cancelled, typically because it has already completed normally; <tt>true</tt> otherwise
*
* @see #isCancelled()
* @see #onCancelled(Object)
*/
/**
* 外部强行打断任务执行的时候调用,正常结束不用调用
*
* @param mayInterruptIfRunning
* @return
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
} /**
* Waits if necessary for the computation to complete, and then retrieves its result.
*
* @return The computed result.
*
* @throws CancellationException
* If the computation was cancelled.
* @throws ExecutionException
* If the computation threw an exception.
* @throws InterruptedException
* If the current thread was interrupted while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
} /**
* Waits if necessary for at most the given time for the computation to complete, and then retrieves its result.
*
* @param timeout
* Time to wait before cancelling the operation.
* @param unit
* The time unit for the timeout.
*
* @return The computed result.
*
* @throws CancellationException
* If the computation was cancelled.
* @throws ExecutionException
* If the computation threw an exception.
* @throws InterruptedException
* If the current thread was interrupted while waiting.
* @throws TimeoutException
* If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
} /**
* Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
*
* <p>
* Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. When first introduced, AsyncTasks were executed serially
* on a single background thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being executed on a single thread to avoid common application errors caused by parallel execution. If you truly want parallel
* execution, you can use the {@link #executeOnExecutor} version of this method with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings on its use.
*
* <p>
* This method must be invoked on the UI thread.
*
* @param params
* The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException
* If {@link #getStatus()} returns either {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
* @see #execute(Runnable)
*/
/**
* 使用默认的串行执行
*
* @param params
* @return
*/
public final MyAsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
} /**
* Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
*
* <p>
* This method is typically used with {@link #THREAD_POOL_EXECUTOR} to allow multiple tasks to run in parallel on a pool of threads managed by AsyncTask, however you can also use your own
* {@link Executor} for custom behavior.
*
* <p>
* <em>Warning:</em> Allowing multiple tasks to run in parallel from a thread pool is generally <em>not</em> what one wants, because the order of their operation is not defined. For example, if
* these tasks are used to modify any state in common (such as writing a file due to a button click), there are no guarantees on the order of the modifications. Without careful work it is possible
* in rare cases for the newer version of the data to be over-written by an older one, leading to obscure data loss and stability issues. Such changes are best executed in serial; to guarantee
* such work is serialized regardless of platform version you can use this function with {@link #SERIAL_EXECUTOR}.
*
* <p>
* This method must be invoked on the UI thread.
*
* @param exec
* The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a convenient process-wide thread pool for tasks that are loosely coupled.
* @param params
* The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException
* If {@link #getStatus()} returns either {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*
* @see #execute(Object[])
*/
/**
* 可以使用该类里面提供的线程池来执行任务
*
* @param exec
* @param params
* @return
*/
public final MyAsyncTask<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;
} /**
* Convenience version of {@link #execute(Object...)} for use with a simple Runnable object. See {@link #execute(Object[])} for more information on the order of execution.
*
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
/**
* 使用默认的串行来执行线程对象
*
* @param runnable
*/
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
} /**
* This method can be invoked from {@link #doInBackground} to publish updates on the UI thread while the background computation is still running. Each call to this method will trigger the
* execution of {@link #onProgressUpdate} on the UI thread.
*
* {@link #onProgressUpdate} will not be called if the task has been canceled.
*
* @param values
* The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
/**
* 如果已经被取消,就不会发送更新进度条
*
* @param values
*/
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
} /**
* 在handler中判断,如果已经被取消就调用onCancelled(result),正常结束调用onPostExecute(result)
*
* @param result
*/
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
} /**
* handler对象
*
* @author liulj
*
*/
private static class InternalHandler extends Handler {
@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 static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
} /**
* handler中传递的对象
*
* @author liulj
*
* @param <Data>
*/
@SuppressWarnings({ "RawUseOfParameterizedType" })
private static class AsyncTaskResult<Data> {
final MyAsyncTask mTask;
final Data[] mData; AsyncTaskResult(MyAsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}
AsyncTask源码解析的更多相关文章
- Android AsyncTask 源码解析
1. 官方介绍 public abstract class AsyncTask extends Object java.lang.Object ↳ android.os.AsyncTask&l ...
- Android -- AsyncTask源码解析
1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+ ...
- Android开发——AsyncTask的使用以及源码解析
.AsyncTask使用介绍 转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52172248 AsyncTask封装了Thread和 ...
- Android源码解析——AsyncTask
简介 AsyncTask 在Android API 3引入,是为了使UI线程能被正确和容易地使用.它允许你在后台进行一些操作,并且把结果带到UI线程中,而不用自己去操纵Thread或Handler.它 ...
- 小白挑战:AsyncTask源码分析
//AsyncTask从本质上讲,是对ThreadPool和handler的封装. 在学习线程池相关的知识时,看到书中提到AsyncTask的实现中使用到了ThreadPool,于是把源码翻了出来, ...
- Android Asynctask与Handler的比较,优缺点区别,Asynctask源码
1 AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以 ...
- 【转载】Xutils3源码解析
Github源码地址:https://github.com/wyouflf/xUtils3 原文地址 :http://www.codekk.com/blogs/detail/54cfab086c476 ...
- Android源码解析系列
转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...
- 还怕问源码?Github上神级Android三方源码解析手册,已有7.6 KStar
或许对于许多Android开发者来说,所谓的Android工程师的工作"不过就是用XML实现设计师的美术图,用JSON解析服务器的数据,再把数据显示到界面上"就好了,源码什么的,看 ...
随机推荐
- EF框架学习手记
转载: [ASP.NET MVC]: - EF框架学习手记 1.EF(Entity Framework)实体框架EF是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架 ...
- Linux IPC System V 消息队列
模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...
- LNMP+zabbix分布式监控搭建及版本升级
LNMP+zabbix分布式监控搭建需要组件:gcc gcc-c++ openssl* pcre pcre-devel gd gd-devel libjpeg-devel libpng-devel l ...
- android 设置布局为无标题样式
<!-- Application theme. --> <style name="AppTheme" parent="android:Theme.Lig ...
- android xml 布局错误(黑掉了)Missing styles. Is the correct theme chosen for this layout?
发现在调整页面的时候 ,老是报以下错误,导致无法静态显示ui效果. Missing styles. Is the correct theme chosen for this layout? Use t ...
- 002.ICMP--拼接ICMP包,实现简单Ping程序(原始套接字)
一.大致流程: 将ICMP头和时间数据设置好后,通过创建好的原始套接字socket发出去.目的主机计算效验和后会将数据原样返回,用当前时间和返回的数据结算时间差,计算出rtt. 二.数据结构: ICM ...
- 在Solr中配置和使用ansj分词
在上一节[编译Ansj之Solr插件]中介绍如何编译ansj分词在solr(lucene)环境中使用的接口,本章将介绍如何在solr中使用ansj,其步骤主要包括:下载或者编译ansj和nlp-lan ...
- PS色调均化滤镜的快捷实现(C#源代码)。
photoshop色调均化功能通常是在进行修片处理前期比较常用的功能之一,其对扩展图像的对比度,增强视觉效果有一定的作用.在很多课本或者文章中,也称这种处理为灰度均衡化.直方图均衡化等等.算法原理都是 ...
- [cocos2d-x]深入--几个代表性的类
摘要: 此文对cocos2d-x引擎中最具代表性,最能体现框架结构的几个类做了简单的介绍, 包括Director,Application, Renderer, EventDispatcher, Sch ...
- 三星s4宣传片配色有惊喜
三星s4宣传片配色有惊喜据了解,一周前,三星曾对外发布了新旗舰手机galaxy s4的宣传视频,不过那份视频里所含信息仅仅只有s4发布会的邀请函.而日前,三星官方发布了s4的第二弹宣传片则暗示该机在配 ...