其他分享
首页 > 其他分享> > Android何时认为窗口泄漏?

Android何时认为窗口泄漏?

作者:互联网

我检查了Android源代码,发现以下方法.
(核心/java/android/view/WindowManagerGlobal.java)

似乎当谁!= 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);
                }
            }
        }
    }

解决方法:

我检查了来源…
我对此不太确定,但我理解她的意思.

“谁”参数仅是活动名称

检查closeAll()调用方法,您可以看到谁只是被破坏的Activity类名称,并且在其后留下了一个窗口:

WindowManagerGlobal.getInstance().closeAll(wtoken,
                        r.activity.getClass().getName(), "Activity");

如果发生泄漏,则调用closeAll()

当Windows已经泄漏时,似乎会调用WindowManagerGlobal.closeAll().因此,谁!= null只是检查以确保String不为NULL.

如果不为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信息.换句话说,它仍然保留在某个窗口中.
> r.mPendingRemoveWindow == null,没有待删除的视图.

因此,这是不一致的.附加了一个视图(还具有mAttachInfo),但是我已经删除了所有挂起的窗口(mPendingRemoveWindow为null)…因此,该视图已泄漏.

希望我能帮到你
问候

参考:

WindowManagerGlobal

ActivityThread

View

标签:android-source,android-view,memory-leaks,android
来源: https://codeday.me/bug/20191118/2028336.html