日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Android解析WindowManagerService(三)Window的删除过程

發布時間:2024/4/14 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android解析WindowManagerService(三)Window的删除过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關文章
Android系統啟動系列
Android深入四大組件系列
Android應用進程啟動過程系列
Android解析WindowManager系列

前言

在本系列文章中,我提到過:Window的操作分為兩大部分,一部分是WindowManager處理部分,另一部分是WMS處理部分,Window的刪除過程也不例外,本篇文章會介紹Window的刪除過程,包括了兩大處理部分的內容。

Window的刪除過程

和Android解析WindowManagerService(二)WMS的重要成員和Window的添加過程這篇文章中Window的創建和更新過程類似,要刪除Window需要先調用WindowManagerImpl的removeView方法,removeView方法中又會調用WindowManagerGlobal的removeView方法,我們就從這里開始講起。為了表述的更易于理解,本文將要刪除的Window(View)簡稱為V。WindowManagerGlobal的removeView方法如下所示。

frameworks/base/core/java/android/view/WindowManagerGlobal.java

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);//1View curView = mRoots.get(index).getView();removeViewLocked(index, immediate);//2if (curView == view) {return;}throw new IllegalStateException("Calling with view " + view+ " but the ViewAncestor is attached to " + curView);}} 復制代碼

注釋1處找到要V在View列表中的索引,在注釋2處調用了removeViewLocked方法并將這個索引傳進去,如下所示。 frameworks/base/core/java/android/view/WindowManagerGlobal.java

private void removeViewLocked(int index, boolean immediate) {ViewRootImpl root = mRoots.get(index);//1View view = root.getView();if (view != null) {InputMethodManager imm = InputMethodManager.getInstance();//2if (imm != null) {imm.windowDismissed(mViews.get(index).getWindowToken());//3}}boolean deferred = root.die(immediate);//4if (view != null) {view.assignParent(null);if (deferred) {mDyingViews.add(view);}}} 復制代碼

注釋1處根據傳入的索引在ViewRootImpl列表中獲得V的ViewRootImpl。注釋2處得到InputMethodManager實例,如果InputMethodManager實例不為null則在注釋3處調用InputMethodManager的windowDismissed方法來結束V的輸入法相關的邏輯。注釋4處調用ViewRootImpl 的die方法,如下所示。

frameworks/base/core/java/android/view/ViewRootImpl.java

boolean die(boolean immediate) {//die方法需要立即執行并且此時ViewRootImpl不在執行performTraversals方法if (immediate && !mIsInTraversal) {//1doDie();//2return false;}if (!mIsDrawing) {destroyHardwareRenderer();} else {Log.e(mTag, "Attempting to destroy the window while drawing!\n" +" window=" + this + ", title=" + mWindowAttributes.getTitle());}mHandler.sendEmptyMessage(MSG_DIE);return true;} 復制代碼

注釋1處如果immediate為ture(需要立即執行),并且mIsInTraversal值為false則執行注釋2處的代碼,mIsInTraversal在執行ViewRootImpl的performTraversals方法時會被設置為true,在performTraversals方法執行完時被設置為false,因此注釋1處可以理解為die方法需要立即執行并且此時ViewRootImpl不在執行performTraversals方法。注釋2處的doDie方法如下所示。
frameworks/base/core/java/android/view/ViewRootImpl.java

void doDie() {//檢查執行doDie方法的線程的正確性checkThread();//1if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);synchronized (this) {if (mRemoved) {//2return;}mRemoved = true;//3if (mAdded) {//4dispatchDetachedFromWindow();//5}if (mAdded && !mFirst) {//6destroyHardwareRenderer();if (mView != null) {int viewVisibility = mView.getVisibility();boolean viewVisibilityChanged = mViewVisibility != viewVisibility;if (mWindowAttributesChanged || viewVisibilityChanged) {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);//7 } 復制代碼

注釋1處用于檢查執行doDie方法的線程的正確性,注釋1的內部會判斷執行doDie方法線程是否是創建V的原始線程,如果不是就會拋出異常,這是因為只有創建V的原始線程才能夠操作V。注釋2到注釋3處的代碼用于防止doDie方法被重復調用。注釋4處V有子View就會調用dispatchDetachedFromWindow方法來銷毀View。注釋6處如果V有子View并且不是第一次被添加,就會執行后面的代碼邏輯。注釋7處的WindowManagerGlobal的doRemoveView方法,如下所示。 frameworks/base/core/java/android/view/WindowManagerGlobal.java

void doRemoveView(ViewRootImpl root) {synchronized (mLock) {final int index = mRoots.indexOf(root);//1if (index >= 0) {mRoots.remove(index);mParams.remove(index);final View view = mViews.remove(index);mDyingViews.remove(view);}}if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {doTrimForeground();}} 復制代碼

WindowManagerGlobal中維護了和 Window操作相關的三個列表,doRemoveView方法會從這三個列表中清除V對應的元素。注釋1處找到V對應的ViewRootImpl在ViewRootImpl列表中的索引,接著根據這個索引從ViewRootImpl列表、布局參數列表和View列表中刪除與V對應的元素。 我們接著回到ViewRootImpl的doDie方法,查看注釋5處的dispatchDetachedFromWindow方法里做了什么: frameworks/base/core/java/android/view/ViewRootImpl.java

void dispatchDetachedFromWindow() {...try {mWindowSession.remove(mWindow);} catch (RemoteException e) {}...} 復制代碼

dispatchDetachedFromWindow方法中主要調用了IWindowSession的remove方法,IWindowSession在Server端的實現為Session,Session的remove方法如下所示。 frameworks/base/services/core/java/com/android/server/wm/Session.java

public void remove(IWindow window) {mService.removeWindow(this, window);} 復制代碼

接著查看WMS的removeWindow方法: frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java

void removeWindow(Session session, IWindow client) {synchronized(mWindowMap) {WindowState win = windowForClientLocked(session, client, false);//1if (win == null) {return;}win.removeIfPossible();//2}} 復制代碼

注釋1處用于獲取Window對應的WindowState,WindowState用于保存窗口的信息,在WMS中它用來描述一個窗口。接著在注釋2處調用WindowState的removeIfPossible方法,如下所示。 frameworks/base/services/core/java/com/android/server/wm/WindowState.java

@Override void removeIfPossible() {super.removeIfPossible();removeIfPossible(false /*keepVisibleDeadWindow*/); } 復制代碼

又會調用removeIfPossible方法,如下所示。 frameworks/base/services/core/java/com/android/server/wm/WindowState.java

private void removeIfPossible(boolean keepVisibleDeadWindow) {...條件判斷過濾,滿足其中一個條件就會return,推遲刪除操作removeImmediately();//1if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) {mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();}mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);Binder.restoreCallingIdentity(origId);} 復制代碼

removeIfPossible方法和它的名字一樣,并不是直接執行刪除操作,而是進行多個條件判斷過濾,滿足其中一個條件就會return,推遲刪除操作。比如這時V正在運行一個動畫,這時就得推遲刪除操作,直到動畫完成。通過這些條件判斷過濾就會執行注釋1處的removeImmediately方法: frameworks/base/services/core/java/com/android/server/wm/WindowState.java

@Overridevoid removeImmediately() {super.removeImmediately();if (mRemoved) {//1if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,"WS.removeImmediately: " + this + " Already removed...");return;}mRemoved = true;//2...mPolicy.removeWindowLw(this);//3disposeInputChannel();mWinAnimator.destroyDeferredSurfaceLocked();mWinAnimator.destroySurfaceLocked();mSession.windowRemovedLocked();//4try {mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);} catch (RuntimeException e) { }mService.postWindowRemoveCleanupLocked(this);//5} 復制代碼

removeImmediately方法如同它的名字一樣,用于立即進行刪除操作。注釋1處的mRemoved為true意味著正在執行刪除Window操作,注釋1到注釋2處之間的代碼用于防止重復刪除操作。注釋3處如果當前要刪除的Window是StatusBar或者NavigationBar就會將這個Window從對應的控制器中刪除。注釋4處會將V對應的Session從WMS的ArraySet<Session> mSessions中刪除并清除Session對應的SurfaceSession資源(SurfaceSession是SurfaceFlinger的一個連接,通過這個連接可以創建1個或者多個Surface并渲染到屏幕上 )。注釋5處調用了WMS的postWindowRemoveCleanupLocked方法用于對V進行一些集中的清理工作,這里就不在繼續深挖下去,有興趣的同學可以自行查看源碼。

Window的刪除過程就講到這里,雖然刪除的操作邏輯比較復雜,但是可以簡單的總結為以下4點:

  • 檢查刪除線程的正確性,如果不正確就拋出異常。
  • 從ViewRootImpl列表、布局參數列表和View列表中刪除與V對應的元素。
  • 判斷是否可以直接執行刪除操作,如果不能就推遲刪除操作。
  • 執行刪除操作,清理和釋放與V相關的一切資源。
  • 總結

    以上是生活随笔為你收集整理的Android解析WindowManagerService(三)Window的删除过程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。