如何从DialogFragment回调至Fragment更新按钮文本
问题:Dialog关闭后更新Fragment内按钮文本
我想在带有DatePicker的Dialog关闭后,更新同一个Fragment内按钮的文本。Dialog在Fragment中实例化,按钮也在该Fragment里。尝试添加onDateChangeListener时出现NullPointerException,求解决思路。
Fragment相关代码
select_dob_btn = view.findViewById(R.id.profile_dob_button); datePickerDialog = new DatePickerDialog(); datePickerDialog.setButtonText("Select Date Of Birth"); select_dob_btn.setText(datePickerDialog.getButtonText());
DatePickerDialog完整代码
public class DatePickerDialog extends DialogFragment { public long dateResult = 0; String buttonText = ""; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity()); LayoutInflater inflater = this.getLayoutInflater(); View custom_layout = inflater.inflate(R.layout.dialog_date_picker,null); DatePicker datePicker = custom_layout.findViewById(R.id.dialog_date_picker); if(dateResult != 0){ datePicker.init(Globals.getDateYearFromTimeStamp(dateResult), Globals.getDateMonthFromTimeStamp(dateResult),Globals.getDateDayFromTimeStamp(dateResult), null); } builder.setView(custom_layout) .setPositiveButton(R.string.submit, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dateResult = Globals.getTimeStampFromDateDDMMYYYY(datePicker.getDayOfMonth()+"-"+(datePicker.getMonth()+1)+"-"+datePicker.getYear()); setButtonText(String.valueOf(Globals.getDateFromTimeStamp(dateResult))); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dateResult = 0; setButtonText(String.valueOf(R.string.register_select_dob)); dialogInterface.cancel(); } }); return builder.create(); } public DatePickerDialog newInstance() { DatePickerDialog f = this; Bundle args = new Bundle(); f.setArguments(args); return f; } public void ShowDialog(FragmentManager fragmentManager) { DialogFragment newFragment = newInstance(); newFragment.show(fragmentManager, String.valueOf(0)); } public void setButtonText(String text){ buttonText = text; } public String getButtonText(){ return buttonText; }
Fragment中用于更新按钮的方法
void RefreshSetBirthdayButton(){ if(datePickerDialog.dateResult == 0){ select_dob_btn.setText(R.string.register_select_dob); }else{ datePickerDialog.setButtonText(String.valueOf(Globals.getDateFromTimeStamp(datePickerDialog.dateResult))); select_dob_btn.setText(datePickerDialog.getButtonText()); } }
解决思路
1. 通过接口回调实现Dialog与Fragment通信
这是Android组件间通信的标准方式,能避免直接引用导致的生命周期问题:
- 在
DatePickerDialog中定义回调接口:public interface OnDateSelectedListener { void onDateSelected(long timestamp, String dateText); void onDateSelectCanceled(); } - 在Dialog类中添加接口实例并在
onAttach中绑定(要求Fragment实现该接口):private OnDateSelectedListener mListener; @Override public void onAttach(Context context) { super.onAttach(context); try { mListener = (OnDateSelectedListener) getParentFragment(); } catch (ClassCastException e) { throw new ClassCastException("Fragment must implement OnDateSelectedListener"); } } - 修改Dialog的按钮点击事件,触发回调:
// 确认按钮点击 @Override public void onClick(DialogInterface dialogInterface, int i) { dateResult = Globals.getTimeStampFromDateDDMMYYYY(datePicker.getDayOfMonth()+"-"+(datePicker.getMonth()+1)+"-"+datePicker.getYear()); String dateText = String.valueOf(Globals.getDateFromTimeStamp(dateResult)); setButtonText(dateText); if(mListener != null){ mListener.onDateSelected(dateResult, dateText); } } // 取消按钮点击 @Override public void onClick(DialogInterface dialogInterface, int i) { dateResult = 0; String cancelText = getString(R.string.register_select_dob); setButtonText(cancelText); if(mListener != null){ mListener.onDateSelectCanceled(); } dialogInterface.cancel(); } - 在Fragment中实现接口并触发更新:
public class YourFragment extends Fragment implements DatePickerDialog.OnDateSelectedListener { // ... 其他代码 @Override public void onDateSelected(long timestamp, String dateText) { datePickerDialog.dateResult = timestamp; RefreshSetBirthdayButton(); } @Override public void onDateSelectCanceled() { datePickerDialog.dateResult = 0; RefreshSetBirthdayButton(); } }
2. 修复Dialog实例不一致问题
当前ShowDialog方法会新建一个Dialog实例,和Fragment中持有的datePickerDialog不是同一个对象,导致数据不同步。修改方法如下:
public void ShowDialog(FragmentManager fragmentManager) { this.show(fragmentManager, String.valueOf(0)); }
3. 规避NullPointerException
- 确保
select_dob_btn在Fragment的onViewCreated或之后初始化,避免按钮未实例化就调用setText。 - 在Dialog初始化DatePicker时,先校验
dateResult的有效性,避免传入无效值调用Globals工具类引发空指针。
内容的提问来源于stack exchange,提问作者user4655559
相关产品推荐
相关产品推荐

