赞
踩
以上都是搜索得来的结论,这里的关键部分还是在ViewRoot,接下来看源码,确认下其内部的UI操作与线程有怎样的联系?
从源码中可以看出:
- public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
- public ViewRootImpl(Context context, Display display) {
- ......
- mThread = Thread.currentThread();
- ......
- }
- ......
- @Override
- public void requestFitSystemWindows() {
- checkThread();
- mApplyInsetsRequested = true;
- scheduleTraversals();
- }
-
- @Override
- public void requestLayout() {
- if (!mHandlingLayoutInLayoutRequest) {
- checkThread();
- mLayoutRequested = true;
- scheduleTraversals();
- }
- }
- ......
- @Override
- public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
- checkThread();
- if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty);
- ......
- }
- ......
- @Override
- public void requestTransparentRegion(View child) {
- // the test below should not fail unless someone is messing with us
- checkThread();
- if (mView == child) {
- ......
- requestLayout();
- }
- }
- ......
- @Override
- public void requestChildFocus(View child, View focused) {
- if (DEBUG_INPUT_RESIZE) {
- Log.v(mTag, "Request child focus: focus now " + focused);
- }
- checkThread();
- scheduleTraversals();
- }
-
- @Override
- public void clearChildFocus(View child) {
- if (DEBUG_INPUT_RESIZE) {
- Log.v(mTag, "Clearing child focus");
- }
- checkThread();
- scheduleTraversals();
- }
-
- @Override
- public void focusableViewAvailable(View v) {
- checkThread();
- if (mView != null) {
- ......
- }
- }
-
- @Override
- public void recomputeViewAttributes(View child) {
- checkThread();
- if (mView == child) {
- ......
- }
- }
- ......
- /**
- * {@inheritDoc}
- */
- @Override
- public void playSoundEffect(int effectId) {
- checkThread();
- ......
- }
- ......
- /**
- * {@inheritDoc}
- */
- @Override
- public View focusSearch(View focused, int direction) {
- checkThread();
- if (!(mView instanceof ViewGroup)) {
- return null;
- }
- return FocusFinder.getInstance().findNextFocus((ViewGroup) mView, focused, direction);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public View keyboardNavigationClusterSearch(View currentCluster,
- @FocusDirection int direction) {
- checkThread();
- return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
- mView, currentCluster, direction);
- }
- ......
- void doDie() {
- checkThread();
- if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
- ......
- }
- ......
- void checkThread() {
- if (mThread != Thread.currentThread()) {
- throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
- }
- }
- ......
- }

以requestLayout()为例,确认下checkThread()之后,还做了什么工作?
在checkThread()之后,仅执行了scheduleTraversals(),深入查看后发现TraversalRunnable.run() > doTraversal(); > performTraversals();中有大量的UI相关的操作。
- void scheduleTraversals() {
- if (!mTraversalScheduled) {
- mTraversalScheduled = true;
- mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
- mChoreographer.postCallback(
- Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);//测量?
- if (!mUnbufferedInputDispatch) {
- scheduleConsumeBatchedInput();//计划消耗批量输入?
- }
- notifyRendererOfFramePending();//通知帧渲染器挂起?
- pokeDrawLockIfNeeded();//如有需要,插入绘制锁?
- }
- }
确认了ViewRoot中的UI操作与线程的相关性,也就是说ViewRoot在哪个线程实例化,那么与之相关的View的UI操作就必须在这个线程中处理。
接下来我们继续看,ViewRoot是在哪里实例化的?
经过搜索,发现ViewRoot的实例化只有两处:
AttachInfo_Accessor不知道是干嘛的,先去看下WindowManagerGlobal都做了什么?
据搜索了解WindowManagerGlobal的作用:
再来看下WindowManagerGlobal的源码中,ViewRootImpl的构造函数是在哪里调用的?
PhoneWindowManager WindowManagerGlobal WindowManagerImpl的作用和关系
从源码中可以看出:
- public final class WindowManagerGlobal {
-
- ......
-
- public void addView(View view, ViewGroup.LayoutParams params,
- Display display, Window parentWindow) {
-
- ......
-
- root = new ViewRootImpl(view.getContext(), display);
-
- view.setLayoutParams(wparams);
-
- mViews.add(view);
- mRoots.add(root);
- mParams.add(wparams);
-
- // do this last because it fires off messages to start doing things
- try {
- root.setView(view, wparams, panelParentView);
- } catch (RuntimeException e) {
- // BadTokenException or InvalidDisplayException, clean up.
- if (index >= 0) {
- removeViewLocked(index, true);
- }
- throw e;
- }
- }
- }
-
- ......
-
- }

什么地方调用了WindowManagerGlobal.addView()?
只在WindowManager的唯一实现类WindowManagerImpl中使用:
- public final class WindowManagerImpl implements WindowManager {
- private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- private final Context mContext;
- private final Window mParentWindow;
-
- private IBinder mDefaultToken;
-
- public WindowManagerImpl(Context context) {
- this(context, null);
- }
-
- private WindowManagerImpl(Context context, Window parentWindow) {
- mContext = context;
- mParentWindow = parentWindow;
- }
-
- public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
- return new WindowManagerImpl(mContext, parentWindow);
- }
-
- public WindowManagerImpl createPresentationWindowManager(Context displayContext) {
- return new WindowManagerImpl(displayContext, mParentWindow);
- }
-
- ......
-
- @Override
- public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
- applyDefaultToken(params);
- mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
- }
- }

WindowManagerImpl.addView()调用的地方很多,那么在Activty中WindowManagerImpl.addView()是在哪个线程?
看下Activity中的实现:
- public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory2,
- Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks2,
- Window.OnWindowDismissedCallback, WindowControllerCallback,
- AutofillManager.AutofillClient {
- ......
- void makeVisible() {
- if (!mWindowAdded) {
- ViewManager wm = getWindowManager();
- wm.addView(mDecor, getWindow().getAttributes());
- mWindowAdded = true;
- }
- mDecor.setVisibility(View.VISIBLE);
- }
- ......
- }

Activity.makeVisible()有三处调用,以下节点依次向上层查询:
其最终实现都是在TransactionExecutor类中,找到TransactionExecutor类的实例化所在的线程,也就找到了Activity中的mDecorView的UI操作所在的线程:
- public class TransactionExecutor {
- ......
- private ClientTransactionHandler mTransactionHandler;
- ......
- public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
- mTransactionHandler = clientTransactionHandler;
- }
- }
- public final class ActivityThread extends ClientTransactionHandler {
- ......
- private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
- ......
- }
找出ActivityThread的实例化在哪个线程?
- public final class ActivityThread extends ClientTransactionHandler {
- ......
- public static ActivityThread systemMain() {
- ......
- ActivityThread thread = new ActivityThread();
- thread.attach(true, 0);
- return thread;
- }
- ......
- public static void main(String[] args) {
- ......
- Looper.prepareMainLooper();
- ......
- ActivityThread thread = new ActivityThread();
- thread.attach(false, startSeq);
-
- Looper.loop();
-
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
- ......
- }

为啥会有主线程与子线程之分?Looper.prepareMainLooper()与Looper.prepare()有什么区别?
-
- public final class Looper {
- ......
- public static void prepare() {
- prepare(true);
- }
-
- private static void prepare(boolean quitAllowed) {
- if (sThreadLocal.get() != null) {
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper(quitAllowed));
- }
-
- /**
- * Initialize the current thread as a looper, marking it as an
- * application's main looper. The main looper for your application
- * is created by the Android environment, so you should never need
- * to call this function yourself. See also: {@link #prepare()}
- */
- public static void prepareMainLooper() {
- prepare(false);
- synchronized (Looper.class) {
- if (sMainLooper != null) {
- throw new IllegalStateException("The main Looper has already been prepared.");
- }
- sMainLooper = myLooper();
- }
- }
- ......
- }

由以上可知Activity.main()运行所在的线程就是主线程了,可是为什么没有看到创建Thread的过程啊?
仅在Thread的类注释中发现:
-
- /**
- * <p>
- * When a Java Virtual Machine starts up, there is usually a single
- * non-daemon thread (which typically calls the method named
- * <code>main</code> of some designated class). The Java Virtual
- * Machine continues to execute threads until either of the following
- * occurs:
- * <ul>
- * <li>The <code>exit</code> method of class <code>Runtime</code> has been
- * called and the security manager has permitted the exit operation
- * to take place.
- * <li>All threads that are not daemon threads have died, either by
- * returning from the call to the <code>run</code> method or by
- * throwing an exception that propagates beyond the <code>run</code>
- * method.
- * </ul>
- */
- public
- class Thread implements Runnable {
- ......
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。