我检查了android的源代码,找到了下面的方法。
(core/java/android/view/WindowManagerGlobal.java
)
当who != null
窗口/视图被泄漏时。有人能解释这背后的原因吗?
public void closeAll(IBinder token, String who, String what) {
synchronized (mLock) {
int count = mViews.size();
//Log.i("foo", "Closing all windows of " + token);
for (int i = 0; i < count; i++) {
//Log.i("foo", "@ " + i + " token " + mParams[i].token
// + " view " + mRoots[i].getView());
if (token == null || mParams.get(i).token == token) {
ViewRootImpl root = mRoots.get(i);
//Log.i("foo", "Force closing " + root);
if (who != null) {
WindowLeaked leak = new WindowLeaked(
what + " " + who + " has leaked window "
+ root.getView() + " that was originally added here");
leak.setStackTrace(root.getLocation().getStackTrace());
Log.e(TAG, "", leak);
}
removeViewLocked(i, false);
}
}
}
}
最佳答案
我查了来源…
我不太确定,但我理解她…
“who”参数仅为活动名称
检查closeAll()
调用方法,可以看到who
只是被破坏并留下一个窗口的活动类名:
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
如果发生泄漏,则调用closeAll()
当窗口已经泄漏时,似乎调用了
WindowManagerGlobal.closeAll()
。所以,who != null
只是一个检查,以确保String
不是NULL
。如果不为空,则创建
WindowLeaked
并打印日志。WindowLeaked
是扩展AndroidRuntimeException
的类。final class WindowLeaked extends AndroidRuntimeException {
public WindowLeaked(String msg) {
super(msg);
}
}
最重要的是,如果调用
WindowManagerGlobal.closeAll()
,则表示窗口已经泄漏。closeAll()调用方法
在
View.java
中,我们可以看到当检测到浸出时调用WindowManagerGlobal.closeAll()
:活动线程.java
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
...
IBinder wtoken = v.getWindowToken();
...
if (wtoken != null && r.mPendingRemoveWindow == null) {
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
}
在上面的代码中,我们可以看到当发现不一致时会触发
WindowManagerGlobal.closeAll()
:wtoken != null
wtoken
表示View
具有mAttachInfo.mWindowToken
信息。换言之,它仍然被某个窗户挡住。r.mPendingRemoveWindow == null
没有要删除的挂起视图。所以,这是不一致的。已附加一个视图(还有一个
mAttachInfo
),但我已删除所有挂起的窗口(mPendingRemoveWindow
为空)。所以,这种观点已经泄露了。希望我能帮你
当做
裁判:
WindowManagerGlobal
ActivityThread
View