android - 处理 dialogFragment 按钮点击
android - handle dialogFragment buttons clicks
我的应用程序中有 Activity,其中只有很少的片段。其中一个片段有一个 DialogFragment,它通过单击按钮调用。 DialogFragment 有 3 个按钮 - 正面、负面和中性。
public class CompanyNotConnectedToSRDialog extends DialogFragment {
public static final String TAG = CompanyNotConnectedToSRDialog.class.getSimpleName();
private NotConnectedDialogListener mNotConnectedDialogListener;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity(), R.style.DefaultAlertDialogTheme)
.setTitle("Register")
.setMessage("Do you really want to register?")
.setNeutralButton("Skip", (dialog1, which) -> {
mNotConnectedDialogListener.onSkipBtnNotConnectedDialogPressed();
})
.setNegativeButton("Cancel", null)
.setPositiveButton("Register", (dialog12, which) -> {
mNotConnectedDialogListener.onSendBtnNotConnectedDialogPressed();
})
.create();
}
public interface NotConnectedDialogListener {
void onSkipBtnNotConnectedDialogPressed();
void onSendBtnNotConnectedDialogPressed();
}
public void setListener(NotConnectedDialogListener listener) {
this.mNotConnectedDialogListener = listener;
}
如您所见,我创建了 public 接口,其中包含用于我的跳过和注册按钮的两种方法(取消按钮侦听器为空,因此无关紧要)和该侦听器的 Setter .
然后我在调用此 dialogFragment 的片段中实现了此接口,我重写了方法并调用了 dialogFragment,如下所示:
if (mNotConnectedDialog == null) {
mNotConnectedDialog = new CompanyNotConnectedToSRDialog();
mNotConnectedDialog.setListener(this);
mNotConnectedDialog.show(getActivity().getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
} else {
mNotConnectedDialog.show(mActivity.getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
mNotConnectedDialog.setListener(this);
}
问题是,如果我按下父 Fragment 中的按钮以显示 DialogFragment、旋转屏幕并按下 DialogFragment 中的任意按钮,我会得到 NullPointerException,因为我的侦听器为空。
java.lang.NullPointerException: Attempt to invoke interface method 'void com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog$NotConnectedDialogListener.onSendBtnNotConnectedDialogPressed()' on a null object reference
at com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog.lambda$onCreateDialog(CompanyNotConnectedToSRDialog.java:31)
如果这个解决方案是错误的,如何处理这些点击和设置监听器?
PS: 请不要告诉我 android:configChanges
.
是的,方向更改后您的侦听器为空。最简单的方法是回调 activity:
public static class DialogFragmentA extends DialogFragment {
// Container Activity must implement this interface
public interface NotConnectedDialogListener {
public void onX();
}
NotConnectedDialogListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (NotConnectedDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement NotConnectedDialogListener");
}
}
...
}
现在您可以在对话框中的任何位置调用 mListener.onX 等,即使在方向更改后也是如此。您的容器 Activity 必须实现接口并将接收方法调用。
https://developer.android.com/guide/components/fragments.html#EventCallbacks
所以当前的解决方案不起作用,因为当您旋转对话框片段时,它会被销毁并重新创建。所以 setListener 没有被调用。解决方案取决于您的侦听器是 activity 还是其他片段。
如果它是 activity,您可以覆盖 DialogFragment 中的 onAttach 并在那里设置侦听器。如果您的侦听器是一个片段,那么在您的 OnCreateDialog 方法中,您可以通过标签查找片段并以这种方式设置侦听器。例如。
Fragment listenerFragment = getActivity().getSupportFragmentManager().findFragmentByTag(getString(R.string.your_listener_fragment_tag));
if( listenerFragment instanceOf NotConnectedDialogListener ) {
listener = (NotConnectedDialogListener) listenerFragment;
} else {
//Handle what to do if you don't have a listener here. Maybe dismiss the dialog.
}
我的应用程序中有 Activity,其中只有很少的片段。其中一个片段有一个 DialogFragment,它通过单击按钮调用。 DialogFragment 有 3 个按钮 - 正面、负面和中性。
public class CompanyNotConnectedToSRDialog extends DialogFragment {
public static final String TAG = CompanyNotConnectedToSRDialog.class.getSimpleName();
private NotConnectedDialogListener mNotConnectedDialogListener;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity(), R.style.DefaultAlertDialogTheme)
.setTitle("Register")
.setMessage("Do you really want to register?")
.setNeutralButton("Skip", (dialog1, which) -> {
mNotConnectedDialogListener.onSkipBtnNotConnectedDialogPressed();
})
.setNegativeButton("Cancel", null)
.setPositiveButton("Register", (dialog12, which) -> {
mNotConnectedDialogListener.onSendBtnNotConnectedDialogPressed();
})
.create();
}
public interface NotConnectedDialogListener {
void onSkipBtnNotConnectedDialogPressed();
void onSendBtnNotConnectedDialogPressed();
}
public void setListener(NotConnectedDialogListener listener) {
this.mNotConnectedDialogListener = listener;
}
如您所见,我创建了 public 接口,其中包含用于我的跳过和注册按钮的两种方法(取消按钮侦听器为空,因此无关紧要)和该侦听器的 Setter . 然后我在调用此 dialogFragment 的片段中实现了此接口,我重写了方法并调用了 dialogFragment,如下所示:
if (mNotConnectedDialog == null) {
mNotConnectedDialog = new CompanyNotConnectedToSRDialog();
mNotConnectedDialog.setListener(this);
mNotConnectedDialog.show(getActivity().getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
} else {
mNotConnectedDialog.show(mActivity.getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
mNotConnectedDialog.setListener(this);
}
问题是,如果我按下父 Fragment 中的按钮以显示 DialogFragment、旋转屏幕并按下 DialogFragment 中的任意按钮,我会得到 NullPointerException,因为我的侦听器为空。
java.lang.NullPointerException: Attempt to invoke interface method 'void com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog$NotConnectedDialogListener.onSendBtnNotConnectedDialogPressed()' on a null object reference
at com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog.lambda$onCreateDialog(CompanyNotConnectedToSRDialog.java:31)
如果这个解决方案是错误的,如何处理这些点击和设置监听器?
PS: 请不要告诉我 android:configChanges
.
是的,方向更改后您的侦听器为空。最简单的方法是回调 activity:
public static class DialogFragmentA extends DialogFragment {
// Container Activity must implement this interface
public interface NotConnectedDialogListener {
public void onX();
}
NotConnectedDialogListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (NotConnectedDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement NotConnectedDialogListener");
}
}
...
}
现在您可以在对话框中的任何位置调用 mListener.onX 等,即使在方向更改后也是如此。您的容器 Activity 必须实现接口并将接收方法调用。
https://developer.android.com/guide/components/fragments.html#EventCallbacks
所以当前的解决方案不起作用,因为当您旋转对话框片段时,它会被销毁并重新创建。所以 setListener 没有被调用。解决方案取决于您的侦听器是 activity 还是其他片段。
如果它是 activity,您可以覆盖 DialogFragment 中的 onAttach 并在那里设置侦听器。如果您的侦听器是一个片段,那么在您的 OnCreateDialog 方法中,您可以通过标签查找片段并以这种方式设置侦听器。例如。
Fragment listenerFragment = getActivity().getSupportFragmentManager().findFragmentByTag(getString(R.string.your_listener_fragment_tag));
if( listenerFragment instanceOf NotConnectedDialogListener ) {
listener = (NotConnectedDialogListener) listenerFragment;
} else {
//Handle what to do if you don't have a listener here. Maybe dismiss the dialog.
}