Android布局控件View?ViewRootImpl?WindowManagerService關(guān)系
1. View,ViewRoot和WindowManager簡(jiǎn)單介紹
1.1 View和ViewGroup
Android的基本布局控件,結(jié)構(gòu)是樹(shù)裝,ViewGroup實(shí)現(xiàn)了ViewParent接口,每個(gè)View內(nèi)部保留一個(gè)ViewParent變量,代表他的父節(jié)點(diǎn)
1.2 ViewRootImpl
ViewRoot概念的具體實(shí)現(xiàn)類(lèi),也實(shí)現(xiàn)了ViewParent接口,每個(gè)View樹(shù)頂級(jí)ViewParent就是這個(gè)類(lèi),主要管理
- View樹(shù)的measure,layout,draw
- 向WindowManagerService注冊(cè)Window
- 接收WindowManagerService的事件回調(diào)
1.3 WindowManager
具體實(shí)現(xiàn)類(lèi)WindowManagerImpl,不過(guò)最終任務(wù)委托給了WindowManagerGlobal對(duì)象,負(fù)責(zé)建立WindowManagerService連接和通信
ViewRootImpl的功能相當(dāng)于中介,左手掌握的頂級(jí)View,右手掌握WindowManger通信
2. ViewRootImpl的起源
2.1 ViewRootImpl創(chuàng)建時(shí)機(jī)
這個(gè)和WindowManager是有點(diǎn)關(guān)聯(lián)的,起點(diǎn)一般是Activity調(diào)用resume的時(shí)機(jī),這個(gè)具體是在ActivityThread類(lèi)中的
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實(shí)際是WindowManager對(duì)象,WindowManager真正做工作的類(lèi)是WindowManagerGlobal
addView()實(shí)際上是添加的DecorView ,從r.window獲取(Activity的話window實(shí)現(xiàn)類(lèi)是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;
}
}
}
}
}
這時(shí)候創(chuàng)建了ViewRootImpl對(duì)象,并把View,ViewRootImpl和windowManagerParam保存到WindowManagerGlobal的集合中,root.setView() 負(fù)責(zé)接力下一棒
2.2 ViewRootImpl通知注冊(cè)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對(duì)象,這里我們也可以發(fā)現(xiàn) 每一個(gè)頂級(jí)View都會(huì)對(duì)應(yīng)一個(gè)ViewRootImpl對(duì)象,this.mWindowSession.addToDisplay() 通過(guò)WindowSession通知WindowManagerService注冊(cè)Window
3.ViewRootImpl與WindowManagerService的通信
3.1 WindowSession
ViewRootImpl向WindowManagerService發(fā)送信息的類(lèi),實(shí)際上是一個(gè)AIDL接口
public interface IWindowSession extends IInterface {}
ViewRootImpl通過(guò)WindowManagerGlobal.getWindowSession() 獲取WindowSession對(duì)象
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;
}
}
前面注冊(cè)Window的時(shí)候就用到的的就是WindowSession對(duì)象的addToDisplay
3.2 IWindow
這個(gè)也是一個(gè)AIDL接口文件,主要是用于WindowManagerService向ViewRootImpl發(fā)送消息,ViewRootImpl調(diào)用mWindowSession.addToDisplay注冊(cè)窗口,會(huì)把IWindow這個(gè)信使帶給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) {
// 省略實(shí)現(xiàn)
}
public void moved(int newX, int newY) {
// 省略實(shí)現(xiàn)
}
public void dispatchAppVisibility(boolean visible) {
// 省略實(shí)現(xiàn)
}
public void dispatchGetNewSurface() {
// 省略實(shí)現(xiàn)
}
public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
// 省略實(shí)現(xiàn)
}
private static int checkCallingPermission(String permission) {
// 省略實(shí)現(xiàn)
}
public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
// 省略實(shí)現(xiàn)
}
public void closeSystemDialogs(String reason) {
// 省略實(shí)現(xiàn)
}
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
// 省略實(shí)現(xiàn)
}
public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras, boolean sync) {
// 省略實(shí)現(xiàn)
}
public void dispatchDragEvent(DragEvent event) {
// 省略實(shí)現(xiàn)
}
public void updatePointerIcon(float x, float y) {
// 省略實(shí)現(xiàn)
}
public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility, int localValue, int localChanges) {
// 省略實(shí)現(xiàn)
}
public void dispatchWindowShown() {
// 省略實(shí)現(xiàn)
}
public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
// 省略實(shí)現(xiàn)
}
public void dispatchPointerCaptureChanged(boolean hasCapture) {
// 省略實(shí)現(xiàn)
}
}
}
我們比較熟悉的可能就是WindowFocusChanged這個(gè)函數(shù)
4. ViewRootImpl與View
這兩個(gè)關(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是刷新方法的起點(diǎn):
主線程Handler設(shè)置同步屏障(postSyncBarrier),讓刷新任務(wù)先執(zhí)行
注冊(cè)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樹(shù)的measure,layout和draw實(shí)現(xiàn)刷新
以上就是Android布局控件View ViewRootImpl WindowManagerService關(guān)系的詳細(xì)內(nèi)容,更多關(guān)于Android布局控件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android?Service啟動(dòng)綁定流程詳解
- android?微信搶紅包工具AccessibilityService實(shí)現(xiàn)詳解
- Android?O對(duì)后臺(tái)Service限制詳解
- Android?NotificationListenerService通知監(jiān)聽(tīng)服務(wù)使用
- Android?NotificationListenerService?通知服務(wù)原理解析
- Android開(kāi)發(fā)InputManagerService創(chuàng)建與啟動(dòng)流程
- Android 10 啟動(dòng)之servicemanager源碼解析
- Android 開(kāi)機(jī)自啟動(dòng)Service實(shí)現(xiàn)詳解
相關(guān)文章
Android使用元數(shù)據(jù)實(shí)現(xiàn)配置信息的傳遞方法詳細(xì)介紹
這篇文章主要介紹了Android使用元數(shù)據(jù)實(shí)現(xiàn)配置信息的傳遞方法,也就是實(shí)現(xiàn)配置快捷菜單功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
Android RecycleView添加head配置封裝的實(shí)例
這篇文章主要介紹了Android RecycleView添加head配置封裝的實(shí)例的相關(guān)資料,這里提供實(shí)例幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08
Android網(wǎng)絡(luò)通信基礎(chǔ)類(lèi)源碼分析講解
這篇文章主要介紹了Android網(wǎng)絡(luò)通信基礎(chǔ)類(lèi)源碼,包括了Handler、Looper、Thread的分析講解,對(duì)日常開(kāi)發(fā)學(xué)習(xí)很有幫助,需要的朋友可以參考下2024-05-05
Android開(kāi)發(fā)之日歷CalendarView用法示例
這篇文章主要介紹了Android開(kāi)發(fā)之日歷CalendarView用法,簡(jiǎn)單分析了日歷CalendarView組件的功能、屬性設(shè)置方法、界面布局、事件監(jiān)聽(tīng)等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03
OpenHarmony實(shí)現(xiàn)屏幕亮度動(dòng)態(tài)調(diào)節(jié)方法詳解
大家在拿到dayu之后,都吐槽說(shuō),會(huì)經(jīng)常熄屏,不利于調(diào)試,那么有沒(méi)有一種辦法,可以讓app不熄屏呢,答案是有的,今天我們就來(lái)揭秘一下,如何控制屏幕亮度2022-11-11
android開(kāi)發(fā)PathEffect問(wèn)題處理
本文主要整理了關(guān)于android中PathEffect的問(wèn)題匯總以及處理方式,以及給大家做了關(guān)于PathEffect類(lèi)的詳細(xì)解釋。2017-11-11

