我正在学习使用Fragment
和DialogFragment
。作为一项培训,我正在尝试扩展the DialogFragment page中给出的AlertDialog
示例。显然一切都很好:当我显示选项菜单并单击其按钮时,会出现一个对话框,其行为与预期一致。但是,如果在显示对话框时配置发生更改(例如,当我旋转屏幕时),则会正确地重新创建对话框,但单击其任何按钮会导致应用程序崩溃。我已经尝试了很多东西(例如,静态newInstance
,setRetainInstance
,onSaveInstanceState
方法和其他记录的建议)来解决问题,但似乎没有任何工作,所以我在初始点。我正在使用支持库v4。
这是我的主要活动代码:
public class MainActivity extends FragmentActivity {
private MyDialogFragment dlgf;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
showMyDialog();
return true;
}
private void showMyDialog(){
dlgf = MyDialogFragment.newInstance();
dlgf.show(getSupportFragmentManager(), "dialog");
}
public void doPositive() {
// do stuff...
dlgf.getDialog().dismiss();
}
public void doNegative() {
// Cancel button pressed
dlgf.getDialog().dismiss();
}
}
这是我的DialogFragment
代码:
public class MyDialogFragment extends DialogFragment {
private View view;
public static MyDialogFragment newInstance() {
MyDialogFragment dlgf = new MyDialogFragment();
return dlgf;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
view = getActivity().getLayoutInflater().inflate(R.layout.alertdialog, null);
return new AlertDialog.Builder(getActivity())
.setView(view)
.setTitle("A Title")
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int buttonID) {
((MainActivity)getActivity()).doPositive();
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int buttonID) {
((MainActivity)getActivity()).doNegative();
}
})
.create();
}
}
单击“取消”按钮后执行崩溃时,logcat会在doNegative方法中显示NullPointerException
。如果在单击“确定”按钮后发生崩溃,则会在doPositive方法中出现NullPointerException
。很明显DialogFragment
对象为空。
答案 0 :(得分:2)
最初在Activity
中设置dlgf
的{{1}}实例在配置更改时被销毁,并且创建了一个新实例。那个新的没有设置showMyDialog()
所以你得到了NPE。
dlgf
内的 getActivity()
将返回Fragment
附加到的当前活动实例。在您的情况下,它将在新实例中正确调用该方法。
要解决您的问题,您只需将导致回调的Fragment
传递给Fragment
,这样您就不必存储对它的引用。
Activity
另一种可能性是让// in activity
public void doPositive(MyDialogFragment source) {
// do stuff...
source.getDialog().dismiss();
}
// in dialog fragment
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int buttonID) {
((MainActivity)getActivity()).doPositive(MyDialogFragment.this);
}
})
使用Activity
/ MyDialogFragment
保留对onRetainNonConfigurationInstance()
的引用。