Android对Window对象的管理机制分析
来源:互联网 发布:pmp含金量 知乎 编辑:程序博客网 时间:2024/06/03 23:43
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/72625679
关于Window对象管理的相关类:
ViewManager
WindowManager
WindowManagerImpl
WindowManagerGlobal
ViewParent
ViewRootImpl
ActvityThread
WindowManagerService
Window是一个抽象类,具体实现类就是 PhoneWindow !
一个Window是通过一个View来承载的,还对应一个ViewRootImpl!
访问Window必须通过WindowManager来实现!
Window具体操作方法实现实在WindowManagerImpl类中,方法定义在ViewManager接口中!
public interface ViewManager{ public void addView(View view, ViewGroup.LayoutParams params); public void updateViewLayout(View view, ViewGroup.LayoutParams params); public void removeView(View view);}
ViewManager接口定义了三个函数,分别对应window的添加,更新和删除!
addView
@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
其实WindowManagerImpl也没有做具体的操作,而是交给了 WindowManagerGlobal
在WindowManagerImpl类中进行了初始化
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
WindowManagerGlobal.java
private WindowManagerGlobal() { } public static WindowManagerGlobal getInstance() { synchronized (WindowManagerGlobal.class) { if (sDefaultWindowManager == null) { sDefaultWindowManager = new WindowManagerGlobal(); } return sDefaultWindowManager; } }
很明显看出这是个单例模式!
private final ArrayList<View> mViews = new ArrayList<View>();private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();private final ArraySet<View> mDyingViews = new ArraySet<View>();
WindowManagerGlobal中有四个重要的集合!
mViews集合存储了所有window对应的View对象!
mRoots集合存储了所有window对应的ViewRootImpl对象
mParams集合存储了所有window对应的布局参数
mDyingViews集合存储了所有正在被删除的window对象
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { // 1. 验证参数! if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } else { final Context context = view.getContext(); if (context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } } ViewRootImpl root; // 一个ViewRootImpl对象 View panelParentView = null; // 一个View对象 synchronized (mLock) { // ... // 查找view对应的index int index = findViewLocked(view, false); if (index >= 0) { if (mDyingViews.contains(view)) {// 如果正在被删除的集合包含该view,则执行ViewRootImpl.doDie()函数 mRoots.get(index).doDie(); } else { throw new IllegalStateException("View " + view + " has already been added to the window manager."); } } // ... // 创建ViewRootImpl对象 root = new ViewRootImpl(view.getContext(), display); // 设置布局参数 view.setLayoutParams(wparams); // 添加view到集合中 mViews.add(view); // 添加ViewRootImpl到集合中 mRoots.add(root); // 添加wparams参数到集合中 mParams.add(wparams); } try { // 将view设置到ViewRootImpl中! root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { // 设置异常则移除view synchronized (mLock) { final int index = findViewLocked(view, false); if (index >= 0) { removeViewLocked(index, true); } } throw e; } }
函数最后通过ViewRootImpl.setView() 来完成window的添加过程!
在setView()内部调用了requestLayout()开启了绘制流程!
View的绘制流程是由ViewRootImpl来完成的!
requestLayout(); 完成绘制流程之后,通过WindowSession来完成Window的添加过程!
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { // ... try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel); } catch (RemoteException e) { mAdded = false; mView = null; mAttachInfo.mRootView = null; mInputChannel = null; mFallbackEventHandler.setView(null); unscheduleTraversals(); setAccessibilityFocus(null, null); throw new RuntimeException("Adding window failed", e); } finally { if (restore) { attrs.restore(); } } // ...}
mWindowSession是IWindowSession类型变量,它是一个Binder对象!
真正的实现者是 Session!
@Override public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) { return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outContentInsets, outStableInsets, outOutsets, outInputChannel); }
这里又通过WindowManagerService来实现window的添加,这样window的添加事务就交给了WMS进行处理!
updateViewLayout
WindowMangerImpl.java
@Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.updateViewLayout(view, params); }
public void updateViewLayout(View view, ViewGroup.LayoutParams params) { // ... final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; // 设置新的布局参数 view.setLayoutParams(wparams); synchronized (mLock) { int index = findViewLocked(view, true); ViewRootImpl root = mRoots.get(index); mParams.remove(index); mParams.add(index, wparams); // 更新mParams集合对应的值 root.setLayoutParams(wparams, false); // 更新ViewRootImpl中的参数, false表示不是一个新的view } }
ViewRooImpl.java
void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { // ... if (newView) { mSoftInputMode = attrs.softInputMode; requestLayout(); } //... mWindowAttributesChanged = true; scheduleTraversals(); } }
在这个函数里面又调用了scheduleTraversals() 来重新进行测量,布局,绘制流程!
removeView
在ViewManager接口中只有一种删除函数:
public void removeView(View view);
但是在WindowManager接口中又增加了一种删除view的方式:
public void removeViewImmediate(View view); // 立即删除
这两种方式,一种表示同步删除,一种表示异步删除!
但是两者都会去调用 WindowManagerGlobal中的 removeView() 函数!
WindowManagerImpl.java
@Override public void removeView(View view) { mGlobal.removeView(view, false); }
@Override public void removeViewImmediate(View view) { mGlobal.removeView(view, true); }
WindowManagerGlobal.java
public void removeView(View view, boolean immediate) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } synchronized (mLock) { // 查找要被删除view的索引 int index = findViewLocked(view, true); // 从mRoots这个集合中得到view对象 View curView = mRoots.get(index).getView(); // 执行删除操作 removeViewLocked(index, immediate); if (curView == view) { return; } throw new IllegalStateException("Calling with view " + view + " but the ViewAncestor is attached to " + curView); } }
removeView() 第二个参数表示是否立刻删除~
private void removeViewLocked(int index, boolean immediate) { // 获取view对应的ViewRootImpl对象 ViewRootImpl root = mRoots.get(index); View view = root.getView(); // ... // 调用View中的die()函数 boolean deferred = root.die(immediate); if (view != null) { view.assignParent(null); if (deferred) { // 添加到正在被删除的集合中 mDyingViews.add(view); } } }
ViewRootImpl.java
boolean die(boolean immediate) { // 立刻删除时,直接执行doDie()函数完成真正的删除操作!然后返回false if (immediate && !mIsInTraversal) { doDie(); return false; } // ... // 异步删除时,发送一个请求删除的消息,然后直接返回true mHandler.sendEmptyMessage(MSG_DIE); return true; }
其实在异步删除时,handler处理的时候也是调用的doDie()函数来完成删除!
case MSG_DIE: doDie(); break;
ViewRootImpl.java
void doDie() { checkThread(); // 检查线程, 很多地方都会调用这个函数! synchronized (this) { if (mRemoved) { // mRemoved默认是false,doDie()函数执行时变为true return; } mRemoved = true; if (mAdded) { // 如果当前window对象应被添加到屏幕上!则需要回调detach函数 dispatchDetachedFromWindow(); } if (mAdded && !mFirst) { destroyHardwareRenderer(); // 停止硬件渲染 if (mView != null) { int viewVisibility = mView.getVisibility(); boolean viewVisibilityChanged = mViewVisibility != viewVisibility; if (mWindowAttributesChanged || viewVisibilityChanged) { // 如果window属性更改或者显示方式改变 try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mWindowSession.finishDrawing(mWindow); } } catch (RemoteException e) { } } mSurface.release(); // 释放资源 } } mAdded = false; // 状态还原 } WindowManagerGlobal.getInstance().doRemoveView(this); }
WindowManagerGlobal.java
void doRemoveView(ViewRootImpl root) { synchronized (mLock) { final int index = mRoots.indexOf(root); if (index >= 0) { mRoots.remove(index);// 从ViewRootImpl集合中删除 mParams.remove(index); // 删除对应的参数 final View view = mViews.remove(index); // 删除对应的view mDyingViews.remove(view);// 从正在被删除的集合中删除view } } if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) { doTrimForeground(); } }
再来看看dispatchDetachedFromWindow()函数
void dispatchDetachedFromWindow() { if (mView != null && mView.mAttachInfo != null) { mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false); mView.dispatchDetachedFromWindow(); // 回调view的detach函数!方法内部会调用onDetachedFromWidow()函数 和 onDetachedFromWindowInternal()函数 } // ... destroyHardwareRenderer(); // ... mSurface.release(); // ... try { mWindowSession.remove(mWindow); } catch (RemoteException e) { } // ... mDisplayManager.unregisterDisplayListener(mDisplayListener); unscheduleTraversals(); }
再次通过IPC方式调用remove()函数!
Session.java
public void remove(IWindow window) { mService.removeWindow(this, window); }
WMS.java
public void removeWindow(Session session, IWindow client) { synchronized(mWindowMap) { WindowState win = windowForClientLocked(session, client, false); if (win == null) { return; } removeWindowLocked(win); } }
void removeWindowLocked(WindowState win) { removeWindowLocked(win, false); }
void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) { win.mWindowRemovalAllowed = true; // ... boolean wasVisible = false; // ... removeWindowInnerLocked(win); // ... }
removeWindowInnerLocked(win); 方法内部分析先暂停!!!
- Android对Window对象的管理机制分析
- cocos2dx对象内存管理机制分析
- Android电源管理机制分析(zz)
- 第十五篇 Android 的Backup服务管理机制与架构分析
- Android 的Backup服务管理机制与架构分析
- 对X window 全面分析的文章
- Android的内存管理机制
- Android的内存管理机制
- String对象的内存管理机制
- MFC线程独立对象管理机制分析
- MFC线程独立对象管理机制分析
- Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
- Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
- Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析
- Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析
- Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析
- mysql Error 1040 too many connection解决办法
- JTA 深度历险
- Spark算子分类及功能描述
- CSS:模型
- 减小unity iOS版包大小方法
- Android对Window对象的管理机制分析
- Oracle 通过UTL_HTTP 发送http请求并处理发送内容中包含空格和特殊字符的问题
- phpcms v9 下拉菜单 二级 三级子栏目调用方法
- 走向三年Java
- pytube——下载YouTube视频的python库
- tensorflow实现对tensor中各个元素求逻辑‘与’
- ajax详解
- java rmi connection refused
- D3.js:坐标轴