上一篇我们分析类AsyncTask原理,但想要真正的掌握还是要动手自己实现一个AsyncTask,下面我们就开始参照AsyncTask源码一步一步的自己动手写一个,毕竟参照大神的写代码才能进步最快,就起名YdsAsyncTask,为啥多了一个yds懒得想名就拿自己的名字做下区分
AsyncTask实现
1,写一个抽象类,实现在子线程要调用的抽象方法
//这里使用泛型限定参数,进度,和返回值
public abstract class YdsAsyncTask<Params,Progress,Result> {
//子线程中要执行的方法接收泛型可变参数,返回要返回的值
public abstract Result doInBackGround(Params... params);
}
2,主线程Handler用于主线程通知更新
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper){
super(looper);
}
}
//主线程Handler用于通知进度更新
private static Handler mInternalHandler;
public YdsAsyncTask(){
mInternalHandler = getMainHandler();
}
//获取主线程handler用于更新主线程进度
public Handler getMainHandler() {
synchronized (YdsAsyncTask.class){
if (mInternalHandler == null){
mInternalHandler = new InternalHandler(Looper.getMainLooper());
}
return mInternalHandler;
}
}
3,子线程WorkerRunnable用于传递参数,和运行子线程执行代码
//用于子线程运行子线程执行的回调
private static abstract class WorkRunnable<Params,Result> implements Callable<Result>{
Params[] mParams;
}
//主线程Handler用于通知进度更新
private static Handler mInternalHandler;
private final WorkRunnable<Params,Result> mWorker:
public YdsAsyncTask(){
mInternalHandler = getMainHandler();
mWorker = new WorkRunnable<Params, Result>() {
@Override
public Result call() throws Exception {
Result result = null;
try {
result = doInBackGround(mParams);
} finally {
}
return result;
}
};
}
4,创建FutureTask用于控制WorkerRunnable
mFutrueTask = new FutureTask<Result>(mWorker){
@Override
protected void done() {
super.done();
//这里在线程执行结束后会返回结果
try {
postResult(get());
} catch (InterruptedException e) {
e.printStackTrace();
postResult(null);
} catch (ExecutionException e) {
e.printStackTrace();
postResult(null);
}
}
};
在执行完workerRunnable后会执行done中方法,经过postResult发送消息,在子线程中调用doPostExecute()
doPostExecute()
private Result postResult(Result result){
Message message = mInternalHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
5,执行线程池创建,消息队列的处理
创建完对象后调用execute(Params... mParams),他最后会调用下面的方法,先执行onPreExecute(),然后将参数赋值给Worker,这个参数里多传了一个sDefaultExecutor来执行代码,那这个是什么呢
public final YdsAsyncTask<Params,Progress,Result> execute(Params... mParams){
return executeOnExecutor(sDefaultExecutor,mParams);
}
private final YdsAsyncTask<Params,Progress,Result> executeOnExecutor(Executor executor,Params... mParams){
onPreExecute();
mWorker.mParams = mParams;
executor.execute(mFutrueTask);
return this;
}
处理传入的Executor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
Runnable mActive = null;
@Override
public void execute(final Runnable runnable) {
mTasks.offer(new Runnable() {
@Override
public void run() {
try{
runnable.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null){
scheduleNext();
}
}
private synchronized void scheduleNext(){
//服务下一个
for (Runnable runnable:mTasks){
Log.i("yyy",runnable.toString());
}
if ((mActive = mTasks.poll()) != null){
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
当执行时会将执行方法添加到mTasks队列中,然后会在从队列中取出任务调用THREAD_POOL_EXECUTOR.execute(mActive),去真正的执行需要执行的代码,我们看下THREAD_POOL_EXECUTOR如何实现
//任务服务线程池
public static final Executor THREAD_POOL_EXECUTOR;
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
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;
private static final int KEEP_ALIVE_SECONDS = 30;
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);
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;
}
这里没有使用系统的线程池,而是基于ThreadPoolExecutor创建一个自己的threadPoolExecutor的线程池,阻塞队列使用的是LinkedBlockingQueue,
总结:
实现一个异步通信并在主线程同时更新view那需要注意一下几点
1,抽象要子类需要复写的方法
2,主线程通讯Handler
3,处理输入任务的队列
4,使用线程池处理任务队列中的数据
网友评论