Android DialogFragment在屏幕旋转时崩溃 [英] Android DialogFragment crash on screen rotation

查看:1096
本文介绍了Android DialogFragment在屏幕旋转时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个DialogFragment类。我必须在每次显示时设置监听器(在我的应用程序中有多种情况)。



但是当我旋转屏幕时,mListener变为null,并且有一个NullPointerExcpetion我点击一个按钮。我不能在活动中实现侦听器,因为它有几个这个对话框的情况,每个都有不同的动作。



CustomDialog类:

  MyDialogListener mListener; 

public void show(FragmentManager fm,MyDialogListener listener){
mListener = listener;
super.show(fm,MyDialog);
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
返回新的AlertDialog.Builder(getActivity())
.setTitle(标题)
.setPositiveButton(android.R.string.ok,new OnClickListener(){
@Override
public void onClick(DialogInterface dialog,int whichButton){
mListener.onDialogPositiveClick ();
//屏幕旋转后的NullPointerException
}
})
.setNegativeButton(android.R.string.cancel,null)
.create() ;
}

活动类:

  public void showMyFirstDialog(){
new CutsomDialog()。show(getFragmentManager(),mFirstListener);
}

public void showMySecondDialog(){
new CutsomDialog()。show(getFragmentManager(),mSecondListener);
}


解决方案

Fragment (包括 DialogFragment )。将本地数据存储在配置更改中的机制是将片段的参数设置为包含您的数据的 Bundle



首先,消除 show()方法;这不是正确的方法。相反,你可以这样做:

  DialogFragment frag = new MyDialogFragment(); 
Bundle args = new Bundle();
args.putString(TITLE,Dialog Title Goes Here);
args.putString(MESSAGE,这是一个对话框messaage);
frag.setArguments(args);

frag.show();

然后,您可以在创建 AlertDialog 时检索标题和消息, code>

  @Override 
public Dialog onCreateDialog(Bundle savedInstanceState){
Bundle args = getArguments();
String title = args.getString(TITLE);
String message = args.getString(MESSAGE);

//设置并返回警报对话框
}

处理 DialogListener 有点复杂。您不想在配置更改中持有该引用,因为它会导致被破坏的活动。相反,您可以安排从片段 onAttach()方法中的活动中检索侦听器:

  @Override 
public void onAttach(Activity activity){
super.onAttach(activity);
//现在将活动转换为您的活动类,并获得参考
//给听众
}

您可能需要更改活动类别才能使其正常工作。如果您从许多活动中使用此对话框片段,那么在此定义一个可以实现的接口来请求监听器,这是非常有用的。然后它会看起来像这样:

  public interface DialogListenerProvider {
DialogListener getDialogListener();
}

@Override
public void onAttach(Activity activity){
super.onAttach(activity);
if(activity instanceof DialogListenerProvider){
mListener =((DialogListenerProvider)activity).getDialogListener();
} else {
//抛出一个错误
}
}


I have a DialogFragment class. I have to set the listener every time it shown (It has multiple cases in my app).

But when I rotate the screen mListener becomes null and there is a NullPointerExcpetion when I click a button. I can't implement the listener in the activity because it has a few cases for this dialog, each has different action.

The CustomDialog class:

MyDialogListener mListener;

public void show(FragmentManager fm, MyDialogListener listener) {
    mListener = listener;
    super.show(fm, "MyDialog");
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
            .setTitle("Title")
            .setPositiveButton(android.R.string.ok, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int whichButton) {
                    mListener.onDialogPositiveClick();
                    // NullPointerException after a screen rotate
                }
            })
            .setNegativeButton(android.R.string.cancel, null)
            .create();
}

The activity class:

public void showMyFirstDialog() {
    new CutsomDialog().show(getFragmentManager(), mFirstListener);
}

public void showMySecondDialog() {
    new CutsomDialog().show(getFragmentManager(), mSecondListener);
}

解决方案

You cannot preserve instance fields of a Fragment (including a DialogFragment). The mechanism for having local data survive configuration changes is to set the fragment's arguments to a Bundle that contains your data; this bundle will survive configuration changes.

First, eliminate the show() method; it's not the correct approach. Instead, you can do something like this:

DialogFragment frag = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("TITLE", "Dialog Title Goes Here");
args.putString("MESSAGE", "This is a dialog messaage");
frag.setArguments(args);

frag.show();

Then you can retrieve the title and message when you create the AlertDialog:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Bundle args = getArguments();
    String title = args.getString("TITLE");
    String message = args.getString("MESSAGE");

    // set up and return the alert dialog as before
}

Dealing with the DialogListener is a little more complex. You don't want to be holding a reference to that across config changes because it will lead back to the destroyed activity. Instead, you can arrange to retrieve the listener from the activity inside the fragment's onAttach() method:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    // now cast activity to your activity class and get a reference
    // to the listener
}

You may need to change your activity class(es) a bit to get this to work right. If you're using this dialog fragment from many activities, it's particularly helpful here to define an interface that the activities can implement to request a listener. It would then look something like this:

public interface DialogListenerProvider {
    DialogListener getDialogListener();
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (activity instanceof DialogListenerProvider) {
        mListener = ((DialogListenerProvider) activity).getDialogListener();
    } else {
        // throw an error
    }
}

这篇关于Android DialogFragment在屏幕旋转时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆