Android AlertDialog导致内存泄漏

时间:2013-04-14 20:26:29

标签: android android-mediaplayer android-alertdialog mediacontroller

美好的一天!斯波克先生在这里。

我为我的Android ErrorListener创建了MediaPlayer。如果我尝试从我的处理程序中显示AlertDialog,则在对话框上按下“确定”按钮时会出现“泄露的窗口”异常。以下是相关的代码段:

班级定义:

public class PlayMediaActivity extends Activity implements OnPreparedListener, OnErrorListener, MediaController.MediaPlayerControl

创建MediaPlayer

mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnErrorListener(this);

mediaController = new MediaController(this);

try {
mediaPlayer.setDataSource(URL);
mediaPlayer.prepareAsync();
mediaPlayer.start();
}
catch(...) {} // Omit real code for brevity.

MediaPlayer准备好的听众:

public void onPrepared(MediaPlayer mediaPlayer) {
    Log.d(TAG, "onPrepared");
    mediaController.setMediaPlayer(this);
    mediaController.setAnchorView(findViewById(R.id.main_audio_view));

    handler.post(new Runnable() {
      public void run() {
        mediaController.setEnabled(true);
        mediaController.show();
      }
    });
  }

MediaPlayer错误监听器:

public boolean onError(MediaPlayer mp, int what, int extra) {

    ShowDialog("Unable to play audio. Try again later.");

    return true;
} 

ShowDialog例程:

private void ShowDialog(String message) {
    // Alert the user something went wrong.
    ContextThemeWrapper cw = new ContextThemeWrapper( PlayMediaActivity.this, R.style.AlertDialogTheme );
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( cw );

    alertDialogBuilder.setTitle("Oops!");

    // set dialog message
    alertDialogBuilder
            .setMessage(message)
            .setCancelable(true) // Allow back hardkey to dismiss
            .setPositiveButton("OK",new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog,int id) {
                    // if this button is clicked, close current activity
                    dialog.dismiss();
                    PlayMediaActivity.this.finish();
                }
              });

    alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {  // Catch back key press.        
        @Override
        public void onCancel(DialogInterface dialog) {
            //do whatever you want the back key to do
            dialog.dismiss();
            PlayMediaActivity.this.finish();
        }
    });

    // create alert dialog
    AlertDialog alertDialog = alertDialogBuilder.create();

    // show it
    alertDialog.show();
}

当我从ShowDialog例程调用onError时,它会弹出,但是当我按下“确定”按钮时,活动会被停止并被销毁但对话框会被泄露(根据堆栈跟踪) ),即使我在完成活动之前打电话给dismiss()

在这类主题上有很多stackoverflow帖子,但没有一个解决了我的问题。我对Android开发很陌生,我的猜测是我做了一些根本错误的事情,但我不能指责它。

有谁看到问题可能是什么?

编辑1 - 包括StackTrace:

04-14 14:38:08.089: E/WindowManager(2099): Activity com.lcboise.lifechurch.PlayMediaActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405619f8 that was originally added here
04-14 14:38:08.089: E/WindowManager(2099): android.view.WindowLeaked: Activity com.lcboise.lifechurch.PlayMediaActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405619f8 that was originally added here
04-14 14:38:08.089: E/WindowManager(2099):  at android.view.ViewRoot.<init>(ViewRoot.java:259)
04-14 14:38:08.089: E/WindowManager(2099):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
04-14 14:38:08.089: E/WindowManager(2099):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
04-14 14:38:08.089: E/WindowManager(2099):  at android.view.Window$LocalWindowManager.addView(Window.java:424)
04-14 14:38:08.089: E/WindowManager(2099):  at android.app.Dialog.show(Dialog.java:241)
04-14 14:38:08.089: E/WindowManager(2099):  at com.lcboise.lifechurch.PlayMediaActivity.ShowDialog(PlayMediaActivity.java:133)
04-14 14:38:08.089: E/WindowManager(2099):  at com.lcboise.lifechurch.PlayMediaActivity.onError(PlayMediaActivity.java:237)
04-14 14:38:08.089: E/WindowManager(2099):  at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:1456)
04-14 14:38:08.089: E/WindowManager(2099):  at android.os.Handler.dispatchMessage(Handler.java:99)
04-14 14:38:08.089: E/WindowManager(2099):  at android.os.Looper.loop(Looper.java:123)
04-14 14:38:08.089: E/WindowManager(2099):  at android.app.ActivityThread.main(ActivityThread.java:3683)
04-14 14:38:08.089: E/WindowManager(2099):  at java.lang.reflect.Method.invokeNative(Native Method)
04-14 14:38:08.089: E/WindowManager(2099):  at java.lang.reflect.Method.invoke(Method.java:507)
04-14 14:38:08.089: E/WindowManager(2099):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
04-14 14:38:08.089: E/WindowManager(2099):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
04-14 14:38:08.089: E/WindowManager(2099):  at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

尝试在UI线程上显示对话框:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        ShowDialog("Unable to play audio. Try again later.");
    }
});

答案 1 :(得分:0)

我建议你不要在方法中创建AlertDialog.Builder。建议在Activity的onCreate方法中创建它,然后使用dialog.dispose()在onDestroy中释放对话框。您的方法可以做的是接收AlertDialog作为参数,并配置它(positiveButton,negativeButton,title,message等),因此在Activity之外正确配置对话框,并正确处理其生命周期以避免不希望的内存泄漏

希望它有所帮助!