WMS(二):Window的删除过程

注释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);//1

View view = root.getView();

if (view != null) {

InputMethodManager imm = InputMethodManager.getInstance();//2

if (imm != null) {

imm.windowDismissed(mViews.get(index).getWindowToken());//3

}

}

boolean deferred = root.die(immediate);//4

if (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) {//1

doDie();//2

return 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();//1

if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);

synchronized (this) {

if (mRemoved) {//2

return;

}

mRemoved = true;//3

if (mAdded) {//4

dispatchDetachedFromWindow();//5

}

if (mAdded && !mFirst) {//6

destroyHardwareRenderer();

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/andr
oid/view/WindowManagerGlobal.java

void doRemoveView(ViewRootImpl root) {

synchronized (mLock) {

final int index = mRoots.indexOf(root);//1

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操作相关的三个列表,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);//1

if (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();//1

if (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

@Override

void removeImmediately() {

super.removeImmediately();

if (mRemoved) {//1

if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,

“WS.removeImmediately: " + this + " Already removed…”);

return;

}

mRemoved = true;//2

mPolicy.removeWindowLw(this);//3

disposeInputChannel();

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

如果你需要这些资料, ⬅ 专栏获取
衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

[外链图片转存中…(img-oWsmNald-1719272383163)]

[外链图片转存中…(img-NCZeq30f-1719272383163)]

[外链图片转存中…(img-OzSkFqOA-1719272383164)]

[外链图片转存中…(img-zMKNMUoM-1719272383164)]

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

如果你需要这些资料, ⬅ 专栏获取

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值