Java 活动在旋转后泄漏了窗口弹出窗口

Java 活动在旋转后泄漏了窗口弹出窗口,java,android,Java,Android,当我在显示弹出菜单的同时旋转设备时,会出现窗口泄漏错误 这是我的弹出菜单: private void showSelectionMenu(View caller) { popup = new PopupMenu(this, caller); // popup.getMenuInflater().inflate(R.menu.selection_menu, popup.getMenu()); popup.inflate(R.menu.selection_menu); po

当我在显示
弹出菜单
的同时旋转设备时,会出现
窗口泄漏
错误

这是我的
弹出菜单

private void showSelectionMenu(View caller) {
    popup = new PopupMenu(this, caller);
//  popup.getMenuInflater().inflate(R.menu.selection_menu, popup.getMenu());
    popup.inflate(R.menu.selection_menu);
    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
        public boolean onMenuItemClick(MenuItem item) {
            Toast.makeText(FileListActivity.this, getString(R.string.selecting)+" "+item.getTitle(), Toast.LENGTH_SHORT).show();
            switch (item.getItemId()) {
                case R.id.select_all:                   mediaFolder.selectAll(); break;
                case R.id.select_none:                  mediaFolder.selectNone(); break;
                case R.id.select_videos:                mediaFolder.selectVideos(); break;
                case R.id.select_pictures:              mediaFolder.selectImages(); break;
                default:                                break;
            }
            findViewById(R.id.buttonRenameSelected).setEnabled(mediaFolder.numberSelected>0);
            cla.redraw();
            return true;
        }
    });
    if (Build.VERSION.SDK_INT >= 14) {
        popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
            @Override
            public void onDismiss(PopupMenu menu) {
                Log.d(TAG, "selectionMenu dismissed");
            }
        });
    }
    popup.show();
}
我知道这里的许多程序员以前都犯过同样的错误,他们通常被告知关闭
onDestroy()
中的菜单。我也是:

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "FileListActivity onDestroy()");
    Log.d(TAG, "onDestroy: popup==null? "+(popup==null));
    if (popup != null) { popup.dismiss(); popup = null; }
    Log.d(TAG, "onDestroy: popup==null? "+(popup==null));

    dataFragment.mRetainedCache = mMemoryCache;
    dataFragment.setData(mediaFolder);
}
这是包含错误的结果日志:

02-10 22:24:15.969 D: FileListActivity onDestroy()
02-10 22:24:15.969 D: onDestroy: popup==null? false
02-10 22:24:15.971 D: selectionMenu dismissed
02-10 22:24:15.971 D: onDestroy: popup==null? true
02-10 22:24:16.064 E: android.view.WindowLeaked: Activity com.myApp.FileListActivity has leaked window android.widget.PopupWindow$PopupDecorView{365b288 V.E...... ......ID 0,0-822,1152} that was originally added here
    at android.view.ViewRootImpl.<init>(ViewRootImpl.java:418)
    at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
    at android.widget.PopupWindow.invokePopup(PopupWindow.java:1378)
    at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:1234)
    at android.support.v7.widget.AppCompatPopupWindow.showAsDropDown(AppCompatPopupWindow.java:78)
    at android.support.v4.widget.PopupWindowCompatKitKat.showAsDropDown(PopupWindowCompatKitKat.java:30)
    at android.support.v4.widget.PopupWindowCompat$KitKatPopupWindowImpl.showAsDropDown(PopupWindowCompat.java:92)
    at android.support.v4.widget.PopupWindowCompat.showAsDropDown(PopupWindowCompat.java:171)
    at android.support.v7.widget.ListPopupWindow.show(ListPopupWindow.java:680)
    at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:163)
    at android.support.v7.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:129)
    at android.support.v7.widget.PopupMenu.show(PopupMenu.java:216)
    at com.myApp.FileListActivity.showSelectionMenu(FileListActivity.java:434)
    at com.myApp.FileListActivity.access$100(FileListActivity.java:44)
    at com.myApp.FileListActivity$5.onClick(FileListActivity.java:186)
    at android.view.View.performClick(View.java:5637)
    at android.view.View$PerformClick.run(View.java:22433)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6126)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
02-10 22:24:16.079 D: FileListActivity onCreate()
编辑2:

我刚刚发现我在运行安卓7.1.1(天堂操作系统,夜间构建)的Nexus 5上出现了这个错误,但在运行Fire OS 5.3.2.1(基于安卓5)的Fire HD 8上没有,在运行安卓4.4.4(CyanogenMod 11)的三星Galaxy S+上也没有。所以,也许这只发生在安卓7上,或者天堂操作系统中有一个bug!? 如果有人拥有官方的安卓7,他/她可以尝试用这个来挑起这个错误。您只需添加以下代码:

@Override
public void onDestroy() {
    super.onDestroy();
    if (popup != null) { popup.dismiss(); popup = null; }
}
并使
弹出窗口
成为类成员变量

编辑3:


这不是天堂的问题。运行Android 7.1.1的Android Studio Emulator中也会出现此错误。

当代码尝试显示弹出窗口时,会出现此错误。活动是在轮换更改后重新创建的,因此我认为您的
调用者
参数包含来自活动的视图。您应该检查调用方参数的来源,并在必要时重新分配。

调用方是一个按钮。它是在onCreate方法中定义的。没错,不是吗?我在我的问题中添加了一些代码。它看起来是正确的。您可以通过清单禁用娱乐。将此
android:configChanges=“keyboardHidden | orientation | screenSize”
添加到您的活动中。谢谢,我知道了。但不建议这样做:“这种技术应该被视为最后的手段”。我更愿意理解我的代码有什么问题。是的,这是同样的行为。在onPause()中取消时也是如此。
@Override
public void onDestroy() {
    super.onDestroy();
    if (popup != null) { popup.dismiss(); popup = null; }
}