说明:最开始接触网络的时候,那时候尝试写了写回调,但自己写不出线程的转换来,就必须在回调方法中写上runOnUiThread方法来切换到主线程。最近研究了一下Android中的线程,一时冲动有了写博客的想法,来记录下自己的成长之路。
Android中一般采用Handler来实现主线程与子线程的切换,这是最常用的,就不再废话了,那么我们来看一下AsyncTask的实现。
AsyncTask的使用前提是,必须在主线程中创建AsyncTask的子类对象,那么这个前提正是可以获取主线程的基础。
private static InternalHandler sHandler;
这是AsyncTask里的一个静态成员变量,显然,它就是线程转换的关键类,下面是InternalHandler的源码
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@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的构造方法中调用了Handler的Handler(Looper looper)这个构造方法,将主线程的looper传入,那么这个handler处理消息就会在looper的线程中执行。
继续来看Handler的源码
public Handler(Callback callback, boolean async) {
......
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这里也证明了如果在一个线程中没有执行Looper.prepare()方法,直接创建Handler是会抛出异常的,mLooper = Looper.myLooper(); 打开Looper的myLooper方法,来看源码
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
可以看到Looper用一个ThreadLocal
Thread currentThread = Thread.currentThread();
其它代码不再贴出,但是到此我们可以看出Looper与创建Looper的线程是相联系的,我们使用Looper来从MessageQueue并交给Handler的HandleMessage来处理
回到主题
在AsyncTask中
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
可以看到在doPackground方法执行完成后会调用postResult方法并将结果传入,来看postResult方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
getHandler的实现
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
可以发现最终会有InternalHandler来执行发送消息的方法,因为InternalHandler肯定是主线程的Handler,那么最终处理消息肯定是在主线程中
来看InternalHandler的handleMessage方法的源码
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;
}
}
由语义就可以看出一个是得到了结果,一个是更新进度
更新进度会调用onProgressUpdate方法,得到结果会调用result.mTask.finish(result.mData[0]);
下面是mTask.finish()方法的源码
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
可以看到如果任务被取消会调用onCancelled方法,否则执行onPostExecute方法
总结:AsyncTask之所以可以在主线程执行进度更新的方法和onPostExecute方法,关键的类就行内部维护了一个肯定在主线程的类InternalHandler,本质就是Handler,由这个类来执行onProgressUpdate与onPostExecute方法,那么就实现了线程的转换。