關於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);
}
- 1
- 2
- 3
- 4
- 5
- 6
ViewManager接口定義了三個函數,分別對應window的添加,更新和刪除!
addView
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
- 1
- 2
- 3
- 4
- 5
其實WindowManagerImpl也沒有做具體的操作,而是交給了 WindowManagerGlobal
在WindowManagerImpl類中進行了初始化
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- 1
WindowManagerGlobal.java
private WindowManagerGlobal() {
}
public static WindowManagerGlobal getInstance() {
synchronized (WindowManagerGlobal.class) {
if (sDefaultWindowManager == null) {
sDefaultWindowManager = new WindowManagerGlobal();
}
return sDefaultWindowManager;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
很明顯看出這是個單例模式!
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>();
- 1
- 2
- 3
- 4
- 5
- 6
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
函數最後通過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();
}
}
// ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
這裏又通過WindowManagerService來實現window的添加,這樣window的添加事務就交給了WMS進行處理!
updateViewLayout
WindowMangerImpl.java
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
- 1
- 2
- 3
- 4
- 5
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
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
ViewRooImpl.java
void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
synchronized (this) {
// ...
if (newView) {
mSoftInputMode = attrs.softInputMode;
requestLayout();
}
//...
mWindowAttributesChanged = true;
scheduleTraversals();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在這個函數裏面又調用了scheduleTraversals() 來重新進行測量,佈局,繪製流程!
removeView
在ViewManager接口中只有一種刪除函數:
public void removeView(View view);
- 1
但是在WindowManager接口中又增加了一種刪除view的方式:
public void removeViewImmediate(View view); // 立即刪除
- 1
這兩種方式,一種表示同步刪除,一種表示異步刪除!
但是兩者都會去調用 WindowManagerGlobal中的 removeView() 函數!
WindowManagerImpl.java
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
- 1
- 2
- 3
- 4
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
- 1
- 2
- 3
- 4
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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
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);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
ViewRootImpl.java
boolean die(boolean immediate) {
// 立刻刪除時,直接執行doDie()函數完成真正的刪除操作!然後返回false
if (immediate && !mIsInTraversal) {
doDie();
return false;
}
// ...
// 異步刪除時,發送一個請求刪除的消息,然後直接返回true
mHandler.sendEmptyMessage(MSG_DIE);
return true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其實在異步刪除時,handler處理的時候也是調用的doDie()函數來完成刪除!
case MSG_DIE:
doDie();
break;
- 1
- 2
- 3
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
再來看看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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
再次通過IPC方式調用remove()函數!
Session.java
public void remove(IWindow window) {
mService.removeWindow(this, window);
}
- 1
- 2
- 3
WMS.java
public void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return;
}
removeWindowLocked(win);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
void removeWindowLocked(WindowState win) {
removeWindowLocked(win, false);
}
- 1
- 2
- 3
void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {
win.mWindowRemovalAllowed = true;
// ...
boolean wasVisible = false;
// ...
removeWindowInnerLocked(win);
// ...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
removeWindowInnerLocked(win); 方法內部分析先暫停!!!