AsyncTask
执行轻量级的异步任务,将结果传递给主线程,主线程根据结果更新UI.
使用
- AsyncTask创建、启动都是在主线程中进行.
AsyncTask<URL, Integer, Long> asyncTask = new AsyncTask<URL, Integer, Long>() {
//以下方法顺序就是调用顺序
@Override
protected void onPreExecute() {
//主线程运行,异步任务开始的准备工作
super.onPreExecute();
}
@Override
protected Long doInBackground(URL... urls) {
//在线程池中执行异步任务
publishProgress();//更新任务进度,通过handler调用onProgressUpdate
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
//主线程运行,异步进度改变就会调用
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Long aLong) {
//住线程运行,异步任务结束后被调用,aLong参数就是doInBackground的返回结果
super.onPostExecute(aLong);
}
//另外还提供了异步任务取消的方法
@Override
protected void onCancelled() {
super.onCancelled();
}
//取消建议调用该方法,
@Override
protected void onCancelled(Long aLong) {
//运行在主线程。用于任务的取消
super.onCancelled(aLong);
}
};
- AsyncTask异步任务的启动、取消
//execute()必须在主线程调用,只能调用一次,多次调用会报错
//想要多次调用就得创建新的asyncTask
//execute()是串行执行
asyncTask.execute();
//并行执行调用方法
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
源码分析
看一下AsyncTask的源码就发现底层实现2个线程池、1个handler.核心线程池THREAD_POOL_EXECUTOR完成实际的任务执行,IntenalHandler完成线程间的切换.
- 线程池的配置
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//核心线程数2-4个
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//最大线程数
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
//非核心线程闲置存活时间为30s
private static final int KEEP_ALIVE_SECONDS = 30;
//线程任务队列容量为128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
//线程工厂,生成AsyncTask # + *名的线程
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());
}
};
--------------------------------------------------------------------------------
执行的线程池决定了任务的执行方式
--------------------------------------------------------------------------------
/**并行线程池
* An {@link Executor} that can be used to execute tasks in parallel.
*/
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;
}
/**串行线程池
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
//SerialExecutor相当于给任务线程排队
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
//THREAD_POOL_EXECUTOR真正的任务执行者
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
- Handler的创建和作用
可以清楚的看到在AsyncTask创建的时候sHandler就创建完成了,AsyncTask在主线程创建,
所以sHandler也在主线程,这就轻松实现了线程间的切换
private static InternalHandler sHandler;
private static Handler getMainHandler() {//静态代码随AsyncTask创建完成创建
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
private static class InternalHandler extends Handler {
public 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://调用publishProgress就会发送该消息
//进度改变回调更新
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);//任务取消
} else {
onPostExecute(result);//任务完成
}
mStatus = Status.FINISHED;
}
网友评论