2017-02-10 73 views
3

当我旋转设备时显示PopupMenu,我得到一个WindowLeaked错误。旋转后活动泄露窗口PopupWindow

这是我PopupMenu

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() 

正如你可以在日志中看到,PopupMenupopup)被罚下场,且错误发生之前设置为null

任何想法发生了什么问题?

编辑:

这就是showSelectionMenu(View caller)被称为(在onCreate):

Button buttonSelectFiles = (Button) findViewById(R.id.buttonSelectFiles); 
buttonSelectFiles.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     showSelectionMenu(v); 
    } 
}); 

编辑2:

我刚刚发现,我得到我的Nexus的错误5运行Android 7.1 .1(LineageOS,每晚构建),但不是运行Fire OS 5.3.2.1(基于Android 5)的Fire HD 8,而不是运行Android 4.4.4(CyanogenMod 11)的Samsung Galaxy S +上。所以也许它只发生在Android 7上,或者可能在LineageOS中有一个错误!? 如果有人有官方的Android 7,他/她可以尝试用这个Android Popup Menu Example来挑起那个错误。你只将不得不添加以下代码:

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    if (popup != null) { popup.dismiss(); popup = null; } 
} 

,并popup类成员变量。

编辑3:

这不是一个LineageOS问题。在运行Android 7.1.1的Android Studio模拟器中也会发生此错误。

+0

是的,这是一样的行为。在onPause()中关闭时也是如此。 – MaxGyver

回答

0

当您的代码尝试显示弹出窗口时发生错误。活动在循环更改后重新创建,因此我认为您的caller参数包含已销毁活动的视图。您应该检查caller参数的来源,并在必要时重新分配。

+0

来电者是一个按钮。它在onCreate方法中定义。这是正确的,不是吗?我已经为我的问题添加了更多代码。 – MaxGyver

+0

它看起来正确。您可以通过清单禁用娱乐功能。将这个'android:configChanges =“keyboardHidden | orientation | screenSize”'添加到您的活动中。 – Hyperion

+1

谢谢,我知道。但不推荐:“这种技术应该被认为是最后的手段”。我想了解我的代码有什么问题。 – MaxGyver

相关问题