多线程系列历史文章:
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 studio编译android M时无法使用org.apache.http.**的解
  2. Android键盘自动弹出解决方法分析
  3. android 学习笔记: manifest.xml中声明多个activity的方法记录
  4. android studio升级方法
  5. 常用的小方法,避免忘记,在此记录一下
  6. Android中获取颜色的几种方法
  7. android中View.measure方法详解
  8. Android SDK下载和更新失败的解决方法
  9. Android代码混淆官方实现方法

随机推荐

  1. 《Pro Android(安卓)Graphics》读书笔记
  2. Android中GridView来显示图片
  3. Get list of photo galleries on Android
  4. android里的ViewGroup
  5. Android(安卓)fragment的数据绑定databin
  6. Android(安卓)程序实时监听网络变化状态
  7. Android(安卓)实现数据的列表显示
  8. Android上实现TCP&UDP的客户端和服务端
  9. android ActionBar的使用
  10. android ndk log使用demo