Android 什么时候认为 window 泄露了?
When does Android consider a window is leaked?
查看了Android源码,发现有如下方法。
(core/java/android/view/WindowManagerGlobal.java
)
似乎 who != null
时 window/view 被泄露了。谁能解释这背后发生了什么?
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" 参数是 Activity 仅名称
查看closeAll()
调用方法,可以看到who
就是Activityclass被销毁留下一个window的名字:
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
如果发生泄漏则调用 closeAll()
似乎 WindowManagerGlobal.closeAll()
在 Windows 已经泄漏时被调用。所以,who != null
它只是检查以确保 String
不是 NULL
。
如果不为空,则创建 WindowLeaked
并打印日志。 WindowLeaked
是扩展 AndroidRuntimeException
的 Class
final class WindowLeaked extends AndroidRuntimeException {
public WindowLeaked(String msg) {
super(msg);
}
}
最重要的是,如果调用 WindowManagerGlobal.closeAll()
,则意味着 Windows 已经泄漏。
CloseAll()调用方法
在View.java
中,我们可以看到当检测到泄漏时调用了WindowManagerGlobal.closeAll()
:
ActivityThread.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
信息。换句话说,它仍然被一些 window. 持有
r.mPendingRemoveWindow == null
没有待删除的视图。
所以,这是不一致的。附加了一个视图(还有 mAttachInfo
)但我已经删除了所有未决的 windows(mPendingRemoveWindow
为空)...因此,该视图已泄漏。
希望能帮到你
此致
REF:
查看了Android源码,发现有如下方法。
(core/java/android/view/WindowManagerGlobal.java
)
似乎 who != null
时 window/view 被泄露了。谁能解释这背后发生了什么?
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" 参数是 Activity 仅名称
查看closeAll()
调用方法,可以看到who
就是Activityclass被销毁留下一个window的名字:
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
如果发生泄漏则调用 closeAll()
似乎 WindowManagerGlobal.closeAll()
在 Windows 已经泄漏时被调用。所以,who != null
它只是检查以确保 String
不是 NULL
。
如果不为空,则创建 WindowLeaked
并打印日志。 WindowLeaked
是扩展 AndroidRuntimeException
final class WindowLeaked extends AndroidRuntimeException {
public WindowLeaked(String msg) {
super(msg);
}
}
最重要的是,如果调用 WindowManagerGlobal.closeAll()
,则意味着 Windows 已经泄漏。
CloseAll()调用方法
在View.java
中,我们可以看到当检测到泄漏时调用了WindowManagerGlobal.closeAll()
:
ActivityThread.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
信息。换句话说,它仍然被一些 window. 持有
r.mPendingRemoveWindow == null
没有待删除的视图。
所以,这是不一致的。附加了一个视图(还有 mAttachInfo
)但我已经删除了所有未决的 windows(mPendingRemoveWindow
为空)...因此,该视图已泄漏。
希望能帮到你 此致
REF: