多线程系列历史文章:
Android/java 多线程(一)-Thread的使用以及源码分析
Android/java 多线程(二)-Thread的好兄弟Handler
Android/java 多线程(三)-HandlerThread的使用场景及源码解析
Android/java多线程(四)-IntentService
Android/java 多线程(五)-ThreadPoolExecutor线程池的使用

简介

一个Android封装好的轻量级异步抽象类,使用的话需要继承并重写部分方法

作用

方便的实现多线程,并能方便的实现主线程与工作线程的通信,并且逻辑都在一个类中,不同于Handler的实现机制在不同的回调中,内部采用线程池管理策略,方便管理

使用介绍

public abstract class AsyncTask {   ....}

可以看到有三个泛型参数,它们的作用分别是:

  • Params 传递给异步任务的参数类型,对应execute()方法和doInBackground()中的参数类型
  • Progress 进度跟新参数类型,对应onProgressUpdate()方法返回的参数类型
  • Result 异步任务执行完毕的返回结果类型,对应doInBackground()方法的返回结果类型和onPostExecute()方法的参数类型

如果不需要使用到,则可以使用Void类代替

简单示例:

申明一个实现类TestAsyncTask,主要打印方法的执行顺序以及参数及运行的线程名称

/** * Created by hj on 2018/12/29. * 说明: */public class TestAsyncTask extends AsyncTask {    @Override    protected void onPostExecute(Integer integer) {        super.onPostExecute(integer);        Log.i("HJ","onPostExecute方法接收的参数值:"+integer+"--"+runThreadName());    }    @Override    protected void onPreExecute() {        super.onPreExecute();        Log.i("HJ","onPreExecute"+"--"+runThreadName());    }    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);        Log.i("HJ","onProgressUpdate:"+ Arrays.toString(values)+"--"+runThreadName());    }    @Override    protected Integer doInBackground(String... strings) {        Log.i("HJ","doInBackground()"+"--"+runThreadName());        publishProgress(50);        return 1;    }    private String runThreadName(){        return "运行在:"+Thread.currentThread().getName()+"线程";    }}

使用:

//必须是在主线程中 TestAsyncTask task = new TestAsyncTask();        task.execute();

打印结果:

I/HJ: onPreExecute--运行在:main线程I/HJ: doInBackground()--运行在:AsyncTask #1线程I/HJ: onProgressUpdate:[50]--运行在:main线程I/HJ: onPostExecute方法接收的参数值:1--运行在:main线程

可以看到,只有doInBackground()方法执行在异步线程中,其他的方法都是运行在主线程中,方法执行顺序为:
onPreExecute()---->doInBackground()---->调用publishProgress()方法---->onProgressUpdate()------>onPostExecute()

下面介绍一下方法的具体作用:

  • onPreExecute 在进行异步任务处理前的一些数据准备工作
  • doInBackground 处理异步任务逻辑,内部可以调用publishProgress更新进度
  • onProgressUpdate 进度更新回调
  • onPostExecute 异步处理完毕后的结果回调 ,处理ui逻辑

源码解析

AsyncTask内部的实现原理为:线程池+Handler

其内部有两个线程池:

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;public static final Executor THREAD_POOL_EXECUTOR;

SERIAL_EXECUTOR对应内部的SerialExecutor内部实现类,主要实现了异步任务的顺序分发:

private static class SerialExecutor implements Executor {        final ArrayDeque mTasks = new ArrayDeque();        Runnable mActive;  //当前要处理的异步任务        //给execute方法加锁保证了顺序执行        public synchronized void execute(final Runnable r) {           //将一个runnable添加进双端队列中            mTasks.offer(new Runnable() {                public void run() {                    try {                        r.run();  //执行                    } finally {                        scheduleNext();                    }                }            });            if (mActive == null) {                scheduleNext();            }        }        //此方法的作用是将SerialExecutor 池中的任务的第一个任务赋值给mActive ,并压入到       //THREAD_POOL_EXECUTOR线程池中        protected synchronized void scheduleNext() {            //poll()方法的作用是删除队列中的第一个并返回结果,如果为null则返回null            if ((mActive = mTasks.poll()) != null) {                //将第一个任务添加到THREAD_POOL_EXECUTOR线程池中                THREAD_POOL_EXECUTOR.execute(mActive);            }        }    }

而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;    }

可以看出它是一个常见的工作线程池,所以,这两个线程池,一个负责消息的任务调度,保证按照顺序执行,另外一个则是真正的异步任务处理池

接下来看一下它的构造方法:

public AsyncTask(@Nullable Looper callbackLooper) {        //初始化一个Handler处理主线程的通信        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()            ? getMainHandler()            : new Handler(callbackLooper);        //初始化一个可以存储Params参数的callable实现,其实也是        //THREAD_POOL_EXECUTOR.execute()的执行回调        mWorker = new WorkerRunnable() {            public Result call() throws Exception {               //里面的回调是不是很熟悉,和HandlerThread类似                mTaskInvoked.set(true); //添加线程标识,用于postResultIfNotInvoked方法的检查                Result result = null;  //这就是onPostExecute()方法的result                try {                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    //noinspection unchecked                    result = doInBackground(mParams); //doInBackground方法在这里执行了                    Binder.flushPendingCommands();                } catch (Throwable tr) {                    mCancelled.set(true); //抛异常了取消任务                    throw tr;                } finally {                    postResult(result); //此方法的作用是将结果发送到主线程                }                return result;            }        };         //初始化一个Future回调,主要用于检查处理结果是否发送        mFuture = new FutureTask(mWorker) {            //done()方法是在callable()方法之后的回调            @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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }//mWorker 的实现    private static abstract class WorkerRunnable implements Callable {        Params[] mParams;  //保存传入的参数    }

接下来看看以上检查的方法的实现:

private void postResultIfNotInvoked(Result result) {        //执行了mWorker 里的call()回调的都会变为true,如果为false,说明任务没有被执行        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }    //将此AsyncTask对象作为message参数发送,接收到之后就会调用finish()方法结束    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }

其中的getHandler()中的Handler的实现类是InternalHandler,来看看它的实现:

    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:                    //result.mData[0]就是从postResult发送过来的AsyncTask对象                    result.mTask.finish(result.mData[0]);  //处理结果分发,回调对应的方法                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);  //这里处理进度更新                    break;            }        }    }  private void finish(Result result) {        // 先判断是否调用了Cancelled()            // 1. 若调用了则执行我们复写的onCancelled()            // 即 取消任务时的操作            if (isCancelled()) {                onCancelled(result);            } else {            // 2. 若无调用Cancelled(),则执行我们复写的onPostExecute(result)            // 即更新UI操作                onPostExecute(result);            }            // 注:不管AsyncTask是否被取消,都会将AsyncTask的状态变更为:FINISHED            mStatus = Status.FINISHED;        }

最后来看一下执行方法execute():

    @MainThread    public final AsyncTask execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }   @MainThread    public final AsyncTask 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; //mWorker中的参数是在这里保存的        exec.execute(mFuture);  //将mFuture对象添加到THREAD_POOL_EXECUTOR 线程池中,mFuture在构造方法中做了初始化。        return this;    }

总结:
1.初始化两个线程池,一个负责任务调度(SerialExecutor),一个负责任务处理THREAD_POOL_EXECUTOR
2.构造方法中实例化了子线程中的callable接口方法,从WorkerRunnable中取出Params对象并赋值给dodoInBackground(mParams)方法执行耗时任务。
3.执行execute()方法将任务提交到THREAD_POOL_EXECUTOR线程池中,并将Params参数赋值到了WorkerRunnable中。
4.调用了postResult(result),通过InternalHandler 将消息回调到了主线程(执行了finish()方法,里面有onPostExecute方法),实现了UI的更新

更多相关文章

  1. Android(安卓)开发指南文档的部分中文翻译
  2. android studio 编译的时候出现的错误和解决方法
  3. Android(安卓)第七天(下午)
  4. android studio编译android M时无法使用org.apache.http.**的解
  5. Android键盘自动弹出解决方法分析
  6. Android程序开发中关于设置全屏无效问题
  7. android dialog小结
  8. http://www.jb51.net/list/list_233_2.htm(导航: 首页 >> 软件编
  9. android 学习笔记: manifest.xml中声明多个activity的方法记录

随机推荐

  1. Settings模块
  2. Android(安卓)Studio通过配置build.gradl
  3. Android(安卓)代码审计工具和常见问题
  4. 判断Service是否运行
  5. [置顶] Android中遇到的需求与解决方案一
  6. [转]Android中Spannable的使用
  7. Android(安卓)简单生成二维码名片
  8. Android(安卓)SDK中各种工具
  9. ActivityManagerService源码分析(一)
  10. cocos2d-x2.2.3和android平台环境的搭建