0

再会!斯波克先生在这里。

ErrorListener为我的 Android创建了一个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();
}

当我ShowDialogonError例程调用时,它会弹出,但是当我按下“确定”按钮时,活动会停止并销毁,但对话框会泄漏(根据堆栈跟踪),即使我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)
4

2 回答 2

0

我建议您不要在方法内创建 AlertDialog.Builder。更推荐在Activity的onCreate方法中创建,然后在onDestroy中用dialog.dispose()释放对话框。您的方法可以做的是接收一个 AlertDialog 作为参数,并对其进行配置(positiveButton、negativeButton、title、message 等),以便在 Activity 外部正确配置对话框,并正确处理其生命周期以避免不必要的内存泄漏

希望能帮助到你!

于 2014-07-08T09:02:02.777 回答
0

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

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        ShowDialog("Unable to play audio. Try again later.");
    }
});
于 2013-05-23T22:29:57.660 回答