国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Window和WindowManager

2019-11-09 19:07:05
字體:
來源:轉載
供稿:網友

Window和WindowManager

Window是一個抽象的概念,每一個Window都對應一個View和一個ViewRootImpl,Window和View通過ViewRootImpl來建立聯系。

在實際使用中無法直接訪問Window,對Window的訪問必須通過Windowmanager。

Window實際上是View的直接管理者

Android中所有的視圖都是通過Window來呈現的,不管是Activity、Dialog還是Toast,它們的視圖實際上是附加在Window上的。

Window的類型

應用Window

對應著一個Activity

子Window

子Window不能單獨存在,它需要附屬在特定的父Window之中,比如Dialog

系統Window

需要聲明權限才能創建的Window,比如Toast和系統狀態欄

Window的層級

層級大的Window會覆蓋層級小的Window,層級對應于WindowManager.LayoutParams的type參數。

應用Window層級范圍:1~999 子Window的層級范圍:1000~1999 系統Window的層級范圍:2000~2999

WindowManger

Window通過WindowManager來訪問,WindowManager是一個接口,它的真正實現是WindowManagerImpl。而WindowmanagerImpl的增刪更新View都交由WindowManagerGlobal來處理。

public final class WindowManagerImpl implements WindowManager { PRivate final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); @Override public void addView(View view, ViewGroup.LayoutParams params) { mGlobal.addView(view, params, mDisplay, mParentWindow); } @Override public void updateViewLayout(View view, ViewGroup.LayoutParams params) { mGlobal.updateViewLayout(view, params); } @Override public void removeView(View view) { mGlobal.removeView(view, false); }}

需要了解的WindowManagerGlobal的幾個重要的參數

//存儲所有Window所對應的Viewprivate final ArrayList<View> mViews = new ArrayList<View>();//存儲所有Window所對應的ViewRootImplprivate final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();//存儲所有Window所對應的布局參數private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();//存儲即將被刪除的View對象 (已經調用removeView方法但是刪除操作還未完成的Window對象)private final ArraySet<View> mDyingViews = new ArraySet<View>();

Window的添加過程

Window的添加過程通過WindowManager的addView來實現

WindowManagerGlobal的addView()

1.檢查參數是否合法,如果是子Window那么還需要調整一些布局參數

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);}

2.創建ViewRootImpl并將View添加到列表中

root = new ViewRootImpl(view.getContext(), display);view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);mParams.add(wparams);

3.通過ViewRootImpl來更新界面并完成window的添加過程

//setView->requestLayout-> ... -> performTraversals -> 開始measure、layout、draw三大流程root.setView(view, wparams, panelParentView);

在來看ViewRootImpl#setView(),Window的添加請求最終交給WindowManagerService處理。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { //... //[重要方法] requestLayout-> ... -> performTraversals -> 開始measure、layout、draw三大流程 requestLayout(); //... try { //通過Windowsession最終完成Window的添加 //mWindowSession是IWindowSession,它是一個Binder對象 [ipC調用] //mWindowSession.addToDisplay -> WindowmanagerService.addWindow mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, 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); } //...}

WIndow的刪除過程

public void removeView(View view, boolean immediate) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } synchronized (mLock) { int index = findViewLocked(view, true); View curView = mRoots.get(index).getView(); //通過index查找待刪除的View removeViewLocked(index, immediate); if (curView == view) { return; } throw new IllegalStateException("Calling with view " + view + " but the ViewAncestor is attached to " + curView); }}

再來看removeViewLocked

private void removeViewLocked(int index, boolean immediate) { ViewRootImpl root = mRoots.get(index); View view = root.getView(); if (view != null) { InputMethodManager imm = InputMethodManager.getInstance(); if (imm != null) { imm.windowDismissed(mViews.get(index).getWindowToken()); } } 具體的刪除操作 boolean deferred = root.die(immediate); if (view != null) { view.assignParent(null); if (deferred) { mDyingViews.add(view); } }}

再來看die方法。如果是同步刪除,立即調用doDie(),如果是異步調用,會通過Handler發送消息調用doDie()。

boolean die(boolean immediate) { // Make sure we do execute immediately if we are in the middle of a traversal or the damage // done by dispatchDetachedFromWindow will cause havoc on return. //立即刪除 -> 同步刪除 (不推薦,容易發生意外) if (immediate && !mIsInTraversal) { doDie(); return false; } if (!mIsDrawing) { destroyHardwareRenderer(); } else { Log.e(TAG, "Attempting to destroy the window while drawing!/n" + " window=" + this + ", title=" + mWindowAttributes.getTitle()); } //異步刪除 mHandler.sendEmptyMessage(MSG_DIE); return true;}

再來看doDie()

void doDie() { //... //真正刪除View dispatchDetachedFromWindow(); //...}

dispatchDetachedFromWindow主要做4件事

垃圾回收相關的工作,比如清除數據和消息,移除回調。 通過Session的remove方法刪除Window:mWindowSession.remove(mWindow),這同樣是一個IPC過程,最終會調用WindowManagerService的removeWindow方法。 調用View的dispatchDetachedFromWindow方法,在內部會調用View的onDetachedFromWindow()以及onDetachedFromWindowInternal()。調用WindowManagerGlobal的doRemoveView方法刷新數據,包括mRoots、mParams以及mDyingViews,需要將當前Window所關聯的這三個對象從列表中刪除。

onDetachedFromWindow() 當View從Window中移除時,這個方法就會被調用。 可以在這個方法內部做一個資源回收工作,比如終止動畫、停止線程。

Window的更新過程

public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } 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); //更新LayoutParams -> scheduleTraversals -> ... -> 開始measure、layout、draw三大流程 root.setLayoutParams(wparams, false); }}

window的更新通過WindowManagerGlobal#updateViewLayout()來完成,內部通過調用VIewRootImpl的setLayoutParams(),然后經過一些列的方法,最終會開始measure、layout、draw三大流程,從而實現window的更新。

其他

參考 《Android藝術開發探索》


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宾阳县| 巴塘县| 关岭| 宜昌市| 上栗县| 三亚市| 麻栗坡县| 庄河市| 肥东县| 东阿县| 武平县| 东丰县| 广昌县| 扎赉特旗| 宁晋县| 察雅县| 郎溪县| 家居| 丹巴县| 庆云县| 新疆| 游戏| 太和县| 永仁县| 虹口区| 屯门区| 固镇县| 白山市| 正镶白旗| 禹城市| 文成县| 布尔津县| 无极县| 屏东县| 阿拉尔市| 合作市| 随州市| 长兴县| 犍为县| 宁德市| 衡山县|