微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐