天天看点

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方法的内部实现,上面以及贴出。