2017-02-10 76 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

相關問題