本篇博文涉及到的一些Android中常用的线程相关知识,源码也比较简单,作为重温笔记。
Android中的线程、线程池,,如下图所示:
AsyncTask
上述方法的执行顺序是:1 -> 2 -> 3 -> 4
对于AsyncTask有如下几点可以从源码中得到验证
- AsyncTask的对象必须在主线程中创建(非必须,后面会讲)
- execute方法必须在UI线程调用(非必须,后面会讲)
- 不要在程序中直接调用onPreExecute、onPostExecute、doInBackground和onProgressUpdate方法
- 一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常
- AsyncTask默认是串行执行任务的,但是我们仍然可以通过AsyncTask的executeOnExecutor方法来并行地执行任务
- AsyncTask 调用 cancel() 任务是否立即停止执行?onPostExecute() 还会被调用吗?onCancelled() 什么时候被调用?
AsyncTask的一般用法如下:
// 除了doInBackground是必须重写的方法,其他的都是可选的实现方法
public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Integer doInBackground(String... strings) {
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
}
@Override
protected void onCancelled(Integer integer) {
super.onCancelled(integer);
}
}
===============================================================
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();// 同步执行
myAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");// 并发执行
myAsyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, "");// 同步执行
源码解读:
如下两点是非必须的:
- AsyncTask的对象必须在主线程中创建
- execute方法必须在UI线程调用
之前看过一些网上的资料还有一些书籍,都说如上的1,2条。但是并未详细的解释为什么要这样。阅读了AsyncTask的源码你会发现,强制要求上面两点是错误的。为什么呢?看源码
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide // 1
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide // 2
*/
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
......
}
如上源码中的1和2处,@hide意味着这两个构造方法是系统使用的而不是给开发者准备的,开发者只能使用第一个无参的构造方法。无参的构造方法会调用上述源码最后一个构造方法,保证了我们可以拿到主线程的Looper。
我们知