Android布局控件View?ViewRootImpl?WindowManagerService關(guān)系
1. View,ViewRoot和WindowManager簡單介紹
1.1 View和ViewGroup
Android的基本布局控件,結(jié)構(gòu)是樹裝,ViewGroup實現(xiàn)了ViewParent接口,每個View內(nèi)部保留一個ViewParent變量,代表他的父節(jié)點
1.2 ViewRootImpl
ViewRoot概念的具體實現(xiàn)類,也實現(xiàn)了ViewParent接口,每個View樹頂級ViewParent就是這個類,主要管理
- View樹的measure,layout,draw
- 向WindowManagerService注冊Window
- 接收WindowManagerService的事件回調(diào)
1.3 WindowManager
具體實現(xiàn)類WindowManagerImpl,不過最終任務(wù)委托給了WindowManagerGlobal對象,負責建立WindowManagerService連接和通信
ViewRootImpl的功能相當于中介,左手掌握的頂級View,右手掌握WindowManger通信
2. ViewRootImpl的起源
2.1 ViewRootImpl創(chuàng)建時機
這個和WindowManager是有點關(guān)聯(lián)的,起點一般是Activity調(diào)用resume的時機,這個具體是在ActivityThread類中的
public final class ActivityThread { final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(4); wm = a.getWindowManager(); LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = 1; l.softInputMode |= forwardBit; if (r.mPreserveWindow) { a.mWindowAdded = true; r.mPreserveWindow = false; ViewRootImpl impl = decor.getViewRootImpl(); if (impl != null) { impl.notifyChildRebuilt(); } } if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; // 核心 wm.addView(decor, l); } else { a.onWindowAttributesChanged(l); } } } else if (!willBeVisible) { r.hideForNow = true; } } }
wm.addView()函數(shù)是入口,wm實際是WindowManager對象,WindowManager真正做工作的類是WindowManagerGlobal
addView()實際上是添加的DecorView ,從r.window獲取(Activity的話window實現(xiàn)類是PhoneWindow)
public final class WindowManagerGlobal { public void addView(View view, android.view.ViewGroup.LayoutParams params, Display display, Window parentWindow) { // 省略非必要代碼 ViewRootImpl root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); this.mViews.add(view); this.mRoots.add(root); this.mParams.add(wparams); try { root.setView(view, wparams, panelParentView); } catch (RuntimeException var13) { if (index >= 0) { this.removeViewLocked(index, true); } throw var13; } } } } }
這時候創(chuàng)建了ViewRootImpl對象,并把View,ViewRootImpl和windowManagerParam保存到WindowManagerGlobal的集合中,root.setView() 負責接力下一棒
2.2 ViewRootImpl通知注冊Window
public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks { public void setView(View view, LayoutParams attrs, View panelParentView) { synchronized(this) { if (this.mView == null) { this.mView = view; // 省略代碼 try { this.mOrigWindowType = this.mWindowAttributes.type; this.mAttachInfo.mRecomputeGlobalAttributes = true; this.collectViewAttributes(); /** * 核心 */ res = this.mWindowSession.addToDisplay(this.mWindow, this.mSeq, this.mWindowAttributes, this.getHostVisibility(), this.mDisplay.getDisplayId(), this.mAttachInfo.mContentInsets, this.mAttachInfo.mStableInsets, this.mAttachInfo.mOutsets, this.mInputChannel); } catch (RemoteException var19) { this.mAdded = false; this.mView = null; this.mAttachInfo.mRootView = null; this.mInputChannel = null; this.mFallbackEventHandler.setView((View)null); this.unscheduleTraversals(); this.setAccessibilityFocus((View)null, (AccessibilityNodeInfo)null); throw new RuntimeException("Adding window failed", var19); } finally { if (restore) { attrs.restore(); } } } } } }
ViewRootImpl保存和View對象,這里我們也可以發(fā)現(xiàn) 每一個頂級View都會對應(yīng)一個ViewRootImpl對象,this.mWindowSession.addToDisplay() 通過WindowSession通知WindowManagerService注冊Window
3.ViewRootImpl與WindowManagerService的通信
3.1 WindowSession
ViewRootImpl向WindowManagerService發(fā)送信息的類,實際上是一個AIDL接口
public interface IWindowSession extends IInterface {}
ViewRootImpl通過WindowManagerGlobal.getWindowSession() 獲取WindowSession對象
public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { // Emulate the legacy behavior. The global instance of InputMethodManager // was instantiated here. // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); } }); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowSession; } }
前面注冊Window的時候就用到的的就是WindowSession對象的addToDisplay
3.2 IWindow
這個也是一個AIDL接口文件,主要是用于WindowManagerService向ViewRootImpl發(fā)送消息,ViewRootImpl調(diào)用mWindowSession.addToDisplay注冊窗口,會把IWindow這個信使帶給WindowManagerService
public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks { static class W extends android.view.IWindow.Stub { private final WeakReference<ViewRootImpl> mViewAncestor; private final IWindowSession mWindowSession; W(ViewRootImpl viewAncestor) { this.mViewAncestor = new WeakReference(viewAncestor); this.mWindowSession = viewAncestor.mWindowSession; } public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId) { // 省略實現(xiàn) } public void moved(int newX, int newY) { // 省略實現(xiàn) } public void dispatchAppVisibility(boolean visible) { // 省略實現(xiàn) } public void dispatchGetNewSurface() { // 省略實現(xiàn) } public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) { // 省略實現(xiàn) } private static int checkCallingPermission(String permission) { // 省略實現(xiàn) } public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { // 省略實現(xiàn) } public void closeSystemDialogs(String reason) { // 省略實現(xiàn) } public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) { // 省略實現(xiàn) } public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras, boolean sync) { // 省略實現(xiàn) } public void dispatchDragEvent(DragEvent event) { // 省略實現(xiàn) } public void updatePointerIcon(float x, float y) { // 省略實現(xiàn) } public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility, int localValue, int localChanges) { // 省略實現(xiàn) } public void dispatchWindowShown() { // 省略實現(xiàn) } public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) { // 省略實現(xiàn) } public void dispatchPointerCaptureChanged(boolean hasCapture) { // 省略實現(xiàn) } } }
我們比較熟悉的可能就是WindowFocusChanged這個函數(shù)
4. ViewRootImpl與View
這兩個關(guān)系緊密,我們最容易接觸到的是ViewRootImpl控制者View的刷新
void scheduleTraversals() { if (!this.mTraversalScheduled) { this.mTraversalScheduled = true; this.mTraversalBarrier = this.mHandler.getLooper().getQueue().postSyncBarrier(); this.mChoreographer.postCallback(2, this.mTraversalRunnable, (Object)null); if (!this.mUnbufferedInputDispatch) { this.scheduleConsumeBatchedInput(); } this.notifyRendererOfFramePending(); this.pokeDrawLockIfNeeded(); } }
scheduleTraversals是刷新方法的起點:
主線程Handler設(shè)置同步屏障(postSyncBarrier),讓刷新任務(wù)先執(zhí)行
注冊mChoreographer.postCallback()接收界面更新的同步消息
接收到刷新的同步消息后,執(zhí)行mTraversalRunnable的run方法,調(diào)用ViewRootImpl.doTraversal()
void doTraversal() { if (this.mTraversalScheduled) { this.mTraversalScheduled = false; this.mHandler.getLooper().getQueue().removeSyncBarrier(this.mTraversalBarrier); if (this.mProfile) { Debug.startMethodTracing("ViewAncestor"); } this.performTraversals(); if (this.mProfile) { Debug.stopMethodTracing(); this.mProfile = false; } } }
this.performTraversals()內(nèi)部調(diào)用performMeasure, performLayout, performDraw View樹的measure,layout和draw實現(xiàn)刷新
以上就是Android布局控件View ViewRootImpl WindowManagerService關(guān)系的詳細內(nèi)容,更多關(guān)于Android布局控件的資料請關(guān)注腳本之家其它相關(guān)文章!
- Android?Service啟動綁定流程詳解
- android?微信搶紅包工具AccessibilityService實現(xiàn)詳解
- Android?O對后臺Service限制詳解
- Android?NotificationListenerService通知監(jiān)聽服務(wù)使用
- Android?NotificationListenerService?通知服務(wù)原理解析
- Android開發(fā)InputManagerService創(chuàng)建與啟動流程
- Android 10 啟動之servicemanager源碼解析
- Android 開機自啟動Service實現(xiàn)詳解
相關(guān)文章
Android使用元數(shù)據(jù)實現(xiàn)配置信息的傳遞方法詳細介紹
這篇文章主要介紹了Android使用元數(shù)據(jù)實現(xiàn)配置信息的傳遞方法,也就是實現(xiàn)配置快捷菜單功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-09-09Android RecycleView添加head配置封裝的實例
這篇文章主要介紹了Android RecycleView添加head配置封裝的實例的相關(guān)資料,這里提供實例幫助大家實現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08Android網(wǎng)絡(luò)通信基礎(chǔ)類源碼分析講解
這篇文章主要介紹了Android網(wǎng)絡(luò)通信基礎(chǔ)類源碼,包括了Handler、Looper、Thread的分析講解,對日常開發(fā)學習很有幫助,需要的朋友可以參考下2024-05-05Android開發(fā)之日歷CalendarView用法示例
這篇文章主要介紹了Android開發(fā)之日歷CalendarView用法,簡單分析了日歷CalendarView組件的功能、屬性設(shè)置方法、界面布局、事件監(jiān)聽等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03OpenHarmony實現(xiàn)屏幕亮度動態(tài)調(diào)節(jié)方法詳解
大家在拿到dayu之后,都吐槽說,會經(jīng)常熄屏,不利于調(diào)試,那么有沒有一種辦法,可以讓app不熄屏呢,答案是有的,今天我們就來揭秘一下,如何控制屏幕亮度2022-11-11