浅析Android Handler消息机制的实现原理

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) {
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值