目录1. View,ViewRoot和WindowManager简单介绍1.1 View和ViewGroup1.2 ViewRootImpl1.3 WindowManager2. V
Android的基本布局控件,结构是树装,ViewGroup实现了ViewParent接口,每个View内部保留一个ViewParent变量,代表他的父节点
ViewRoot概念的具体实现类,也实现了ViewParent接口,每个View树顶级ViewParent就是这个类,主要管理
具体实现类WindowManagerImpl,不过最终任务委托给了WindowManagerGlobal对象,负责建立WindowManagerService连接和通信
ViewRootImpl的功能相当于中介,左手掌握的顶级View,右手掌握WindowManger通信
这个和WindowManager是有点关联的,起点一般是Activity调用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()函数是入口,wm实际是WindowManager对象,WindowManager真正做工作的类是WindowManagerGlobal
addView()实际上是添加的DecorView ,从r.window获取(Activity的话window实现类是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;
}
}
}
}
}
这时候创建了ViewRootImpl对象,并把View,ViewRootImpl和windowManagerParam保存到WindowManagerGlobal的集合中,root.setView() 负责接力下一棒
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对象,这里我们也可以发现 每一个顶级View都会对应一个ViewRootImpl对象,this.mWindowSession.addToDisplay() 通过WindowSession通知WindowManagerService注册Window
ViewRootImpl向WindowManagerService发送信息的类,实际上是一个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
这个也是一个AIDL接口文件,主要是用于WindowManagerService向ViewRootImpl发送消息,ViewRootImpl调用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) {
// 省略实现
}
public void moved(int newX, int newY) {
// 省略实现
}
public void dispatchAppVisibility(boolean visible) {
// 省略实现
}
public void dispatchGetNewSurface() {
// 省略实现
}
public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
// 省略实现
}
private static int checkCallingPermission(String permission) {
// 省略实现
}
public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
// 省略实现
}
public void closeSystemDialogs(String reason) {
// 省略实现
}
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
// 省略实现
}
public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras, boolean sync) {
// 省略实现
}
public void dispatchDragEvent(DragEvent event) {
// 省略实现
}
public void updatePointerIcon(float x, float y) {
// 省略实现
}
public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility, int localValue, int localChanges) {
// 省略实现
}
public void dispatchWindowShown() {
// 省略实现
}
public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
// 省略实现
}
public void dispatchPointerCaptureChanged(boolean hasCapture) {
// 省略实现
}
}
}
我们比较熟悉的可能就是WindowFocusChanged这个函数
这两个关系紧密,我们最容易接触到的是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设置同步屏障(postSyncBarrier),让刷新任务先执行
注册mChoreographer.postCallback()接收界面更新的同步消息
接收到刷新的同步消息后,执行mTraversalRunnable的run方法,调用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()内部调用performMeasure, performLayout, performDraw View树的measure,layout和draw实现刷新
以上就是Android布局控件View ViewRootImpl WindowManagerService关系的详细内容,更多关于Android布局控件的资料请关注编程网其它相关文章!
--结束END--
本文标题: Android布局控件View ViewRootImpl WindowManagerService关系
本文链接: https://lsjlt.com/news/195485.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0