0. 背景描述
Android
系统出于简单、高效的考虑,基于单线程模型对View
体系进行设计实现,因此多个线程对同一个View
执行操作时不是线程安全的。简单是因为不用考虑和处理多线程环境下操作View
带来的线程安全问题,高效是因为无需通过额外的手段来处理多线程安全问题,效率不会受到影响(通过加锁等方式解决线程安全问题会引入额外的性能开销)。之所以在设计实现时考虑简单和高效,也是因为Android
应用属于UI
交互型应用,因此需要Android
系统提供高效的实现来保障用户体验足够流畅。基于单线程模型,用户操作也是在UI
线程中进行处理的,因此,UI
线程不适合处理网络请求、本地IO
等这一类耗时操作,否则会导致用户的操作不能被及时处理,给用户带来不好的使用体验。
为了在单线程模型下可以保证用户的交互体验,Android
系统引入Handler
机制来实现线程切换的能力,从而解决不能在UI
线程执行耗时操作的问题。当然,Handler
机制不只用于解决子线程无法更新UI
的问题,还可用于实现延时任务。
说明:
Android
中的UI
线程指的是主线程,因此下文中提到的UI
线程和主线程实际上是指同一个线程。
补充:Android
系统对UI
操作所在线程的限制对应的源码如下:
// android.app.ActivityThread
public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {
...
@UnsupportedAppUsage
final H mH = new H(); // 主线程创建的Handler
// An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
...
public static void main(String[] args) {
...
// 1. 创建主线程的Looper
Looper.prepareMainLooper();
...
// 2. 在主线程创建ActivityThread实例
ActivityThread thread = new ActivityThread();
// 3. 在主线程将ActivityThread实例通过Binder传递到SystemServer进程
thread.attach(false, startSeq);
...
// 4. 开启主线程的死循环用于获取各种消息并处理
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
class H extends Handler {
public static final int BIND_APPLICATION = 110;
public static final int EXECUTE_TRANSACTION = 159;
...
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
// 5. SystemServer通过Binder调用到App进程,执行Application的创建以及生命周期的调用
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
case EXECUTE_TRANSACTION:
// 6. SystemServer通过Binder调用到App进程,执行Activity的生命周期
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
...
}
}
}
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest, boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
...
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
...
if (r.window == null && !a.mFinished && willBeVisible) {
...
if (a.mVisibleFromClient) {
// 8. 执行完onResume之后,向WindowManagerImpl添加DecorView
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
...
}
}
} else if (!willBeVisible) {
...
}
}
@VisibleForTesting
public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest, String reason) {
try {
...
r.activity.performResume(r.startsNotResumed, reason);
...
} catch (Exception e) {
...
}
return true;
}
}
// android.app.servertransaction.TransactionExecutor
public class TransactionExecutor {
private ClientTransactionHandler mTransactionHandler; // 持有了android.app.ActivityThread的实例
public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
mTransactionHandler = clientTransactionHandler;
}
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
...
}
public void executeCallbacks(ClientTransaction transaction) {
...
for (int i = 0; i < size; ++i) {
...
if (postExecutionState != UNDEFINED && r != null) {
// Skip the very last transition and perform it by explicit state request instead.
final boolean shouldExcludeLastTransition = i == lastCallbackRequestingState && finalState == postExecutionState;
cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
}
}
}
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
final int start = r.getLifecycleState();
...
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
// 7. 执行Activity的一系列生命周期函数
performLifecycleSequence(r, path, transaction);
}
private void performLifecycleSequence(ActivityClientRecord r, IntArray path, ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
...
switch (state) {
...
case ON_RESUME:
// 调用了ActivityThread的handleResumeActivity方法
mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,
r.isForward, false /* shouldSendCompatFakeFocus */,
"LIFECYCLER_RESUME_ACTIVITY");
break;
...
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
}
// android.view.WindowManagerGlobal
public final class WindowManagerGlobal {
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) {
...
ViewRootImpl root;
synchronized (mLock) {
...
// 9. 主线程创建ViewRootImpl实例
if (windowlessSession == null) {
root = new ViewRootImpl(view.getContext(), display);
} else {
root = new ViewRootImpl(view.getContext(), display, windowlessSession);
}
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
// 10. 请求VSYNC信号开启下一帧绘制
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
...
}
}
}
}
// android.view.ViewRootImpl
public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks, AttachedSurfaceControl {
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session, boolean useSfChoreographer) {
...
// 因为在主线程执行,所以mThread为主线程
mThread = Thread.currentThread();
...
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
@Override
public void invalidateChild(View child, Rect dirty) {
invalidateChildInParent(null, dirty);
}
@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
checkThread();
...
}
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");
}
}
}
@UiThread
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
public void invalidate() {
invalidate(true);
}
@UnsupportedAppUsage
public void invalidate(boolean invalidateCache) {
invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
}
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate) {
...
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
final ViewParent p = mParent;
if (p != null && ai != null && l < r && t < b) {
final Rect damage = ai.mTmpInvalRect;
damage.set(l, t, r, b);
p.invalidateChild(this, damage);
}
...
}
}
}
根据源码可知,无论是调用ViewRootImpl#requestLayout
还是View#invalidate
来对UI
进行更新,最终都会调用ViewRootImpl#checkThread
检查当前线程与创建ViewRootImpl
实例时所在的线程是否一致,不一致将会抛出异常。ViewRootImpl
实例是SystemServer
进程的AMS
通过Binder
调用到App
进程后,经过ActivityThread#mH
切换到主线程进行创建的,因此更新UI
的线程不是主线程将会抛出异常。
1. 目的用途
Handler
机制是Android
系统实现的消息机制,常见用途是在子线程执行耗时任务,执行完之后再切换到主线程执行UI
操作,此外Handler
机制还支持执行延时任务。
补充:线程切换可以理解为线程间通信,线程间通信一般分为显式通信和隐式通信,显式通信一般是通过发消息的方式来实现,隐式通信则是通过共享内存(静态变量的读写)来实现。Android
中的Handler
机制类似于前者,通过发送消息进行线程间通信。
2. 使用方式
在分析实现原理之前,先对Handler
的使用方式进行说明,有利于从使用的角度倒推实现原理。Handler
的使用包括三个步骤:创建Handler
实例、使用Handler
发送消息以及使用Handler
处理消息。
2.1. 创建Handler实例
public class Handler {
@UnsupportedAppUsage
final Looper mLooper;
final MessageQueue mQueue;
@UnsupportedAppUsage
final Callback mCallback;
final boolean mAsynchronous;
// 使用给定的Looper对象创建Handler对象
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
// 使用给定的Looper对象创建Handler对象,并传入callback参数用于处理消息。
public Handler(@NonNull Looper looper, @Nullable Callback callback) {
this(looper, callback, false);
}
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
}
创建Handler
对象时必须传递一个Looper
对象,然后Handler
对象持有Looper
对象以及MessageQueue
对象(由Looper
对象直接持有)。因此,有必要分析下Looper
对象的创建过程。
public final class Looper {
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@UnsupportedAppUsage
final MessageQueue mQueue;
final Thread mThread;
// 构造一个Looper对象,根据quitAllowed决定是否可以退出消息循环
private Looper(boolean quitAllowed) {