1. AsyncTask 简介

AsyncTask是一个抽象类,它是由Android封装的一个轻量级异步类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。

2.实例

先看下效果:

代码如下:

public class MainActivity extends AppCompatActivity {    private TextView mTv;    private Button mBtn;    private int mNum = 0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mTv = findViewById(R.id.mTv);        mBtn = findViewById(R.id.mBtn);        mBtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new MyAsyncTask().execute("I am zuowei.zhang");            }        });    }    private class MyAsyncTask extends AsyncTask {        @Override        protected void onPreExecute() {            super.onPreExecute();            mNum = 0;            mTv.setText("0");        }        @Override        protected Void doInBackground(String... strings) {            Log.e("zzw", strings[0].toString());            while (mNum < 100) {                try {                    Thread.sleep(100);                    mNum++;                    publishProgress(mNum);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            return null;        }        @Override        protected void onProgressUpdate(Integer... values) {            mTv.setText(String.valueOf(values[0]));            super.onProgressUpdate(values);        }        @Override        protected void onPostExecute(Void aVoid) {            Toast.makeText(getApplicationContext(), "运行结束", Toast.LENGTH_SHORT).show();            super.onPostExecute(aVoid);        }    }}

2.1 AsyncTask的核心方法 

2.1.1 onPreExecute

这个方法在异步任务开始执行之前调用。在主线程执行,主要用于进行一些界面上的初始化操作。

2.1.2 doInBackground

这个方法中的所有代码会在子线程中运行,在这个方法中处理耗时操作。在这个方法中不可用进行UI操作。在此任务中调用publishProgress 方法,将子线程运行过程中的数据传递给主线程。

2.1.3 onProgressUpdate

当子线程中调用了publishProgress方法后,这个方法就会被调用,方法中携带的参数是从子线程中传递过来的。

2.1.4 onPostExecute

当doInBackground的代码执行完毕,并通过return 进行返回时候,这个方法就会被调用。返回的数据会作为参数传递到此方法中。

上面几个方法的调用顺序为: onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()。

3.源码分析

AsyncTask是一个抽象类,需要创建一个类来继承它,此抽象类带有三个泛型的参数,

public abstract class AsyncTask {    ...    ...}

三个泛型类型参数的含义如下:
**Params:**开始异步任务执行时传入的参数类型;
**Progress:**异步任务执行过程中,返回下载进度值的类型;
**Result:**异步任务执行完成后,返回的结果类型;

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

    public AsyncTask() {    //1        this((Looper) null);    }    public AsyncTask(@Nullable Handler handler) {    //2        this(handler != null ? handler.getLooper() : null);    }    public AsyncTask(@Nullable Looper callbackLooper) {    //3        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()            ? getMainHandler()            : new Handler(callbackLooper);        mWorker = new WorkerRunnable() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Result result = null;                try {                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    //noinspection unchecked                    result = doInBackground(mParams);                    Binder.flushPendingCommands();                } catch (Throwable tr) {                    mCancelled.set(true);                    throw tr;                } finally {                    postResult(result);                }                return result;            }        };        mFuture = new FutureTask(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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }

AsyncTask内部有三种不同参数的构造方法。如前面第2步的实例,一般很少重写构造方法,所以内部调用的是第1个构造方法。最终调用到第3个构造方法。在此方法中,Handler 是由 方法 getMainHandler 获取:

    private static Handler getMainHandler() {        synchronized (AsyncTask.class) {            if (sHandler == null) {                sHandler = new InternalHandler(Looper.getMainLooper());            }            return sHandler;        }    }

创建一个主线程的Handler。

继续看第3个构造方法中还初始化了两个变量,mWorker和mFuture。这两个变量留着后面的步骤分析。

启动AsyncTask的时候,调用的是方法 execute。

    @MainThread    public final AsyncTask execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }

调用了executeOnExecutor 方法,这个方法的代码如下:

    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;        exec.execute(mFuture);        return this;    }

在此方法会维护一个全局变量 mStatus 来判断当前任务的运行状态。而且在这里看到了AsyncTask 中的第一个方法 onPreExecute(),此方法处于AsyncTask 开始运行时前调用到。把参数 params 传递到 mWorker 中,并且 调用了exec.execute(mFuture),把构造方法中创建的 mFuture传递进去了。

exec 对象往上追是 sDefaultExecutor,而这个AsyncTask中创建的对象:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

而 SERIAL_EXECUTOR 为:public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

再看SerialExecutor类:

    private static class SerialExecutor implements Executor {        final ArrayDeque mTasks = new ArrayDeque();        Runnable mActive;        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.execute(mActive);            }        }    }

SerialExecutor 是个静态内部类,在这个类中维护了一个队列,通过锁使得该队列确保AsyncTask中的任务是一个个加入到队列中,执行完一个才执行下一个。 

在这个方法中主要有两个步骤:

a. 向队列中加入一个新的任务,即之前实例化后的mFuture对象

b. 调用 scheduleNext()方法,调用THREAD_POOL_EXECUTOR执行队列头部的任务。

SerialExecutor 类仅仅为了保持任务执行是串行的,实际执行是由 THREAD_POOL_EXECUTOR 完成。

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

 THREAD_POOL_EXECUTOR 是一个线程池,开启了一定数量的核心线程和工作线程。然后调用线程池的execute 方法去执行线程。从上面的流程可以看出,执行的线程是mFuture。

这时候在回头看看mFuture和mWorker:

        mWorker = new WorkerRunnable() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Result result = null;                try {                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                    //noinspection unchecked                    result = doInBackground(mParams);                    Binder.flushPendingCommands();                } catch (Throwable tr) {                    mCancelled.set(true);                    throw tr;                } finally {                    postResult(result);                }                return result;            }        };        mFuture = new FutureTask(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 occurred while executing doInBackground()",                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }

在mWorker 中的call 方法执行了耗时操作,也就是 doInBackground 方法。当执行完毕后调用了 postResult(result) 方法:

    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }

此方法会把result 传递给了内部的Handler跳转到主线程中,通过前面的分析,内部的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:                    // There is only one result                    result.mTask.finish(result.mData[0]);                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);                    break;            }        }    }

在 InternalHandler中,如果接受到的消息是 MESSAGE_POST_RESULT ,就会调用 finish 方法:

    private void finish(Result result) {        if (isCancelled()) {            onCancelled(result);        } else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }

这时候会判断任务是否取消,如果取消则调用onCancelled()方法,如果正常执行完成则会调用 onPostExecute() 方法。在doInBackground 方法中,经常会调用 publishProgress() 方法来传递进度,看下此方法的源码:

    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult(this, values)).sendToTarget();        }    }

在此方法中,会发送消息为 MESSAGE_POST_PROGRESS 到 Handler 中,在Handler接收到消息时候会调用到方法 onProgressUpdate()。这样 AsyncTask 的核心方法就都执行到了。

更多相关文章

  1. android apk如何引用系统framework.jar,settingslib.jar
  2. Android海康监控视频调用demo
  3. Android中pendingIntent的深入理解
  4. Android线程优先级规定及其设置的具体方法
  5. Android(安卓)性能优化:多线程
  6. Android(安卓)Jetpack -- Lifecycle
  7. 【Android(安卓)消息处理】Handler、Looper、Message 源码浅析
  8. Android(安卓)学习笔记——旋转模拟器方向,全屏,窗口生命周期
  9. Activity销毁时如何保存Fragment状态

随机推荐

  1. Set集合就这么简单!
  2. Unity平台 | 快速集成华为性能管理服务
  3. 模板方法模式在开源代码中应用
  4. 4: zabbix5.0自动发现网站域名并监控访问
  5. 接了烂代码的项目,怎么玩好?
  6. 分享几个写并发题遇到的坑
  7. 如何写高质量的代码(完结)
  8. 多线程基础必要知识点!看了学习多线程事半
  9. 想要的资源就在那,为什么你总是搜不到?
  10. 三十