DialogFragment方向变化时使用getActivity()导致崩溃

5

我目前遇到了DialogFragments的一些问题。 我正在使用最新的v.4支持包(我相信是第8版)。 我的问题是,如果我的手机在对话框打开时改变方向,应用程序会开始表现出奇怪的行为。

目前我的应用程序的工作方式如下: 有一个FragmentActivity,它调用一个Fragment。 然后,该Fragment通过getActivity().getSupportFragmentManager()调用一个DialogFragment。

如果方向在对话框打开时发生变化,则Fragment中的getActivity() = null。 如果我想结束Activity等操作,这会导致问题。

要引起此问题,您需要打开对话框,更改方向并按下按钮。只有在按下按钮后才会崩溃。

我的DialogFragment称为AlertDialogFragment:

public class AlertDialogFragment extends DialogFragment {
private static Builder mBuilder;
private static DialogInterface.OnClickListener mListener;

public static AlertDialogFragment newInstance(Context context, DialogInterface.OnClickListener listener) {
    mBuilder = new AlertDialog.Builder(context);
    mListener = listener;       
    return new AlertDialogFragment();
}

//... some functions to set Icons etc

public void setButton(int whichButton, CharSequence buttonText) {
    final DialogInterface.OnClickListener listener = mListener == null ? null : mListener;      
    mBuilder.setPositiveButton(buttonText, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                listener.onClick(dialog, whichButton);
            }
    });
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return mBuilder.create();
}
}

这是代码片段:
public class TestBedFragment extends Fragment implements DialogInterface.OnClickListener   {
// onCreateView Stuff  

private void showCrashDialog() {
    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    AlertDialogFragment newDialog = AlertDialogFragment.newInstance(getActivity(), this);
    newDialog.setTitle("Test");     
    newDialog.setIcon(android.R.drawable.ic_dialog_alert);
    newDialog.setMessage("Testing testing testing... 1, 2, 3... Just press Ok.");
    newDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Ok");
    newDialog.show(ft, "dialog");

    // Cause the problem. Simulate the user turning the screen
    getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

@Override
public void onClick(DialogInterface dialog, int which) {

    /*
     * hexnumber = a hex number
     * Normally equals: TestBedFragment{hexnumber #0 id=hexnumber}
     * With crash equals: TestBedFragment{hexnumber}
     */
    Log.e("TestBedFragment", "this = " + this);

    /*
     * hexnumber = a hex number
     * Normally equals: com.example.TestBed.TestBedActivity@hexnumber
     * With crash equals: null
     */
    Log.e("TestBedFragment", "getActivity() = " + getActivity()); // Will equal null... ???

    getActivity().finish();
}
}

我不太确定是什么导致了这个问题?如果这是一个愚蠢的问题,那我很抱歉。我在其他地方读到过关于“Window Leaking”的内容,但我在logcat中没有看到任何相关信息。
有人能帮助我吗 :) 非常感谢
谢谢
3个回答

2
您需要了解Activity的生命周期。每次旋转设备时,Activity都会重新创建。这意味着该类的新实例正在执行。
在您的代码中发生的情况是,在旋转后,侦听器调用先前对话框实例上的getActivity,引用先前的Activity。但是此Activity不再有效,它已经在旋转后被“销毁”,并出现了一个新的Activity。
您对getActivity的调用不再有效。
您不能在片段onDestroy方法期间关闭打开的对话框吗?

2
您可以在onPause()中关闭对话框,并使用条件检查并在onCreate()中显示对话框。根据您具体的使用情况,这可能更适用于onStop()或onDestroy()。
@Override
protected void onPause() {
    if (myDialog != null && myDialog.isVisible())
        myDialog .dismiss();
    super.onPause();
}

0

您正在重新创建所有内容,而不是使用bundle。在您的onCreateDialog中添加一个if来检查空bundle。如果它为空,则执行创建操作,否则不执行任何操作,Android将从bundle中恢复所有内容。

我认为这将解决您的问题。

if(SavesIinstanceState == null); {
    // your code
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接