上篇文章已经分析了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方法的内部实现,上面以及贴出。