天天看點

Window删除過程分析

上篇文章已經分析了Window的建立過程,這篇文章繼續分析Window的删除過程,WindowManager調用removeView(View view)方法,最終執行的是其實作類WindowMangerImpl的removeView(View view)方法下面看看WindowManagerImpl的removeView方法的源碼:

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

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java

 @Override
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }
           

可以看到這個方法的移除view的操作是委托給了WindowManagerGlobal的removeView()方法來完成的。下面來看看

WindowManagerGlobal的removeView方法的源碼:

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

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java

public void removeView(View view, boolean immediate) {
        //... 省略部分代碼

        synchronized (mLock) {
            int index = findViewLocked(view, true);
            View curView = mRoots.get(index).getView();
	        // 關鍵代碼
            removeViewLocked(index, immediate);

           //... 省略部分代碼
        }
    }

    private void removeViewLocked(int index, boolean immediate) {
        ViewRootImpl root = mRoots.get(index);
        View view = root.getView();

        //... 省略部分代碼

	    //關鍵代碼
        boolean deferred = root.die(immediate);

        if (view != null) {
            view.assignParent(null);
            if (deferred) {
		// 關鍵代碼
                mDyingViews.add(view);
            }
        }
    }
           

removeViewLocked方法中,調用了ViewRootImpl的die方法,下面看看這個方法的源碼:

/frameworks/base/core/java/android/view/ViewRootImpl.java
 
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/ViewRootImpl.java

 boolean die(boolean immediate) {

        if (immediate && !mIsInTraversal) {
	       // 1  關鍵代碼  
            doDie();
            return false;
        }

	   // ... 省略部分代碼

	   // 2  關鍵代碼
        mHandler.sendEmptyMessage(MSG_DIE);
        return true;
}
    

// doDie方法的具體實作
void doDie() {
        checkThread();

        synchronized (this) {
            if (mRemoved) {
                return;
            }
            mRemoved = true;
            if (mAdded) {
		        //關鍵代碼
                dispatchDetachedFromWindow();
            }

            // ... 省略部分代碼
        }
	    // 關鍵代碼
        WindowManagerGlobal.getInstance().doRemoveView(this);
}
           

上面的die方法中如果傳入的immediate參數為true,則表示立即(同步)删除,如果傳入的immediate是false,則會通過

mHandler.sendEmptyMessage(MSG_DIE);進行異步删除。下面先看看立即(同步)删除的邏輯,上面的doDie方法又調用到了dispatchDetachedFromWindow();方法,下面看看這個方法的實作:

/frameworks/base/core/java/android/view/ViewRootImpl.java
 
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/ViewRootImpl.java

void dispatchDetachedFromWindow() {
        mFirstInputStage.onDetachedFromWindow();
        if (mView != null && mView.mAttachInfo != null) {
            mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
            mView.dispatchDetachedFromWindow();
        }

        // ... 省略部分代碼
        try {
	    // 關鍵代碼 ,這裡通過IPC和WindowManagerService進行通信,SystemServer程序中,
	    // 調用Session的remove方法
	    // 最終還是調用了WindowManagerService的removeWindow方法,将window移除。
            mWindowSession.remove(mWindow);
        } catch (RemoteException e) {
        }

        // ... 省略部分代碼
    }
           

這個方法内部其實是通過WindowManagerService在用戶端的代理對象mWindowSession調用remove方法移除window,

這個方法調用會向SystemServer程序發起通信,調用Session類的remove方法,下面看看這個方法的具體實作:

/frameworks/base/services/core/java/com/android/server/wm/Session.java

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java

 @Override
    public void remove(IWindow window) {
        mService.removeWindow(this, window);
    }
           

這個方法内部最終還是調用了WindowManagerService的removeWindow方法,将window移除。這個步驟是完成了SystemServer程序中移除Window的操作,接着在app程序,我們要将WindowManagerGlobal類中儲存的關于window的各種相關的參數都清除。下面看看WindowManagerGlobal的doRemoveView()方法,下面看看這個方法的源碼:

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

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java

void doRemoveView(ViewRootImpl root) {
        synchronized (mLock) {
            final int index = mRoots.indexOf(root);
            if (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的view的相關資訊的幾個集合中,和這個window

相關的資訊都移除掉。

接着在看看異步删除view的邏輯:

ViewRootImpl類内部是有一個ViewRootHandler類型的handler的

final ViewRootHandler mHandler = new ViewRootHandler();
final class ViewRootHandler extends Handler {
	    // ... 省略部分代碼
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
		        // ... 省略部分代碼
                case MSG_DIE:
		          //關鍵代碼
                    doDie();
                    break;
                // ... 省略部分代碼
            }
        }
    }
           

在handler内部收到MSG_DIE這個消息後,調用了ViewRootImpl類的doDie()方法進行window的移除操作。doDie方法的内部實作,上面以及貼出。