DialogFragment 方向更改崩溃与 getActivity()

Posted

技术标签:

【中文标题】DialogFragment 方向更改崩溃与 getActivity()【英文标题】:DialogFragment Orientation Change Crash with getActivity() 【发布时间】:2012-05-19 13:15:30 【问题描述】:

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

目前我的应用程序是这样工作的: 有一个FragmentActivity,它调用一个Fragment。 然后这个 Fragment 调用一个 DialogFragment(通过 getActivity().getSupportFragmentManager()。

如果在打开对话框时方向发生变化,则 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: TestBedFragmenthexnumber #0 id=hexnumber
     * With crash equals: TestBedFragmenthexnumber
     */
    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();


我不太确定这是什么原因造成的?对不起,如果这是一个愚蠢的问题。我在其他地方读过有关“Windows 泄漏”的信息,但我没有在 logcat 中看到任何提及这些内容的内容。

谁能帮帮我:)非常感谢

谢谢

【问题讨论】:

【参考方案1】:

您必须了解 Activity 生命周期。每次旋转设备时,都会重新创建活动。这意味着该类的一个新实例正在执行。

在您的代码中发生的情况是,在旋转之后,侦听器在前一个对话框实例上调用 getActivity,引用前一个活动。但是这个活动已经失效了,轮换后已经“销毁”了,又出现了一个新的活动。

您调用 getActivity 不再有效。

你不能在片段 onDestroy 方法期间关闭你打开的对话框吗?

【讨论】:

【参考方案2】:

您正在重新创建所有内容,而不是使用捆绑包。将if 添加到您的 onCreateDialog 以检查空包。如果它为 null,则执行您的创建工作,否则什么也不做,Android 将从包中恢复所有内容。

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

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

【讨论】:

【参考方案3】:

您可以在 onPause() 中关闭对话框,并在 onCreate() 中使用条件检查和显示对话框。根据您的具体用例,这可能更适合 onStop() 或 onDestroy()。

@Override
protected void onPause() 
    if (myDialog != null && myDialog.isVisible())
        myDialog .dismiss();
    super.onPause();

【讨论】:

以上是关于DialogFragment 方向更改崩溃与 getActivity()的主要内容,如果未能解决你的问题,请参考以下文章

方向更改时的 DialogFragment 回调

重叠DialogFragment,在方向更改时以错误的顺序重新创建

方向更改时应用程序崩溃

当Webview方向更改然后按下后退按钮时,应用程序崩溃

ActionBarSherlock:方向更改 ICS 时可折叠项目崩溃

无明显原因的方向更改后应用程序崩溃