Java 通过AlertDialogFragment中的Bundle传递侦听器-可能吗?
我有一个简单的课程:Java 通过AlertDialogFragment中的Bundle传递侦听器-可能吗?,java,android,Java,Android,我有一个简单的课程: public class AlertDialogFragment extends DialogFragment { private static final DialogInterface.OnClickListener DUMMY_ON_BUTTON_CLICKED_LISTENER = new DialogInterface.OnClickListener() { @Override public void onClick(Di
public class AlertDialogFragment extends DialogFragment {
private static final DialogInterface.OnClickListener DUMMY_ON_BUTTON_CLICKED_LISTENER = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
};
public static final class Builder implements Parcelable {
public static final Creator<Builder> CREATOR = new Creator<Builder>() {
@Override
public Builder createFromParcel(Parcel source) {
return new Builder(source);
}
@Override
public Builder[] newArray(int size) {
return new Builder[size];
}
};
private Optional<Integer> title;
private Optional<Integer> message;
private Optional<Integer> positiveButtonText;
private Optional<Integer> negativeButtonText;
public Builder() {
title = Optional.absent();
message = Optional.absent();
positiveButtonText = Optional.absent();
negativeButtonText = Optional.absent();
}
public Builder(Parcel in) {
title = (Optional<Integer>) in.readSerializable();
message = (Optional<Integer>) in.readSerializable();
positiveButtonText = (Optional<Integer>) in.readSerializable();
negativeButtonText = (Optional<Integer>) in.readSerializable();
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeSerializable(title);
out.writeSerializable(message);
out.writeSerializable(positiveButtonText);
out.writeSerializable(negativeButtonText);
}
@Override
public int describeContents() {
return 0;
}
public Builder withTitle(Integer title) {
this.title = Optional.fromNullable(title);
return this;
}
public Builder withMessage(Integer message) {
this.message = Optional.fromNullable(message);
return this;
}
public Builder withPositiveButton(int buttonText) {
this.positiveButtonText = Optional.fromNullable(buttonText);
return this;
}
public Builder withNegativeButton(int buttonText) {
this.negativeButtonText = Optional.fromNullable(buttonText);
return this;
}
private void set(AlertDialog.Builder dialogBuilder, final AlertDialogFragment alertDialogFragment) {
if (title.isPresent()) {
dialogBuilder.setTitle(title.get());
}
if (message.isPresent()) {
dialogBuilder.setMessage(message.get());
}
if (positiveButtonText.isPresent()) {
dialogBuilder.setPositiveButton(positiveButtonText.get(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialogFragment.onPositiveButtonClickedListener.onClick(dialog, which);
}
});
}
if (negativeButtonText.isPresent()) {
dialogBuilder.setNegativeButton(negativeButtonText.get(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialogFragment.onNegativeButtonClickedListener.onClick(dialog, which);
}
});
}
}
public AlertDialogFragment build() {
return AlertDialogFragment.newInstance(this);
}
}
private static final String KEY_BUILDER = "builder";
private DialogInterface.OnClickListener onPositiveButtonClickedListener = DUMMY_ON_BUTTON_CLICKED_LISTENER;
private DialogInterface.OnClickListener onNegativeButtonClickedListener = DUMMY_ON_BUTTON_CLICKED_LISTENER;
private static AlertDialogFragment newInstance(Builder builder) {
Bundle args = new Bundle();
args.putParcelable(KEY_BUILDER, builder);
AlertDialogFragment fragment = new AlertDialogFragment();
fragment.setArguments(args);
return fragment;
}
public void setOnPositiveButtonClickedListener(DialogInterface.OnClickListener listener) {
this.onPositiveButtonClickedListener = listener != null ? listener : DUMMY_ON_BUTTON_CLICKED_LISTENER;
}
public void setOnNegativeButtonClickedListener(DialogInterface.OnClickListener listener) {
this.onNegativeButtonClickedListener = listener != null ? listener : DUMMY_ON_BUTTON_CLICKED_LISTENER;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
Builder builder = getArguments().getParcelable(KEY_BUILDER);
builder.set(alertDialogBuilder, this);
return alertDialogBuilder.create();
}
}
但现在我应该这样设置侦听器:
AlertDialogFragment dialogFragment = new AlertDialogFragment.Builder()
.withTitle(R.string.no_internet_connection)
.withMessage(messageId)
.withPositiveButton(android.R.string.ok)
.build();
dialogFragment.setOnPositiveButtonClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_NO_INTERNET_CONNECTION);
AlertDialogFragment.newInstance(
getString(R.string.example_parameter),
object : AlertDialogFragment.Companion.AlertDialogListener {
override fun primaryActionClicked() {
// DO SOMETHING ABOUT THE ACTION
}
}
).show(childFragmentManager, AlertDialogFragment::class.java.name)
也许将按钮单击侦听器直接设置为DialogFragment
实例而不是通过Bundle
参数传递它们是不安全的,因为向Fragment
传递参数的推荐方法是通过Bundle
参数传递它们
我知道在Android中与
Fragment
s通信的推荐方式是强制主机活动实现回调接口。但通过这种方式,在运行时抛出ClassCastException
之前,活动是否应该实现此接口并不清楚。而且它还具有很强的依赖性——要在活动之外的某个地方使用它,我应该在活动中实现回调
接口。因此,我不能在主机活动的Fragment
s“独立”中使用它:prepareAlertDialogFragment().show(getActivity().getSupportFragmentManager(),“tag”)代码>听起来,您希望有一个警报对话框,它可以有自己的侦听器,可以响应按钮按下事件(有点像OnClickListener)。我实现这一点的方法是创建一个自定义DialogFragment以及一个扩展Parcelable的侦听器
confirmonceldialogfragment.java
public interface ConfirmOrCancelDialogListener extends Parcelable {
void onConfirmButtonPressed();
void onCancelButtonPressed();
}
这是您的对话框实现。除了通过对newInstance的静态方法调用实例化它的方式外,它的处理方式与片段非常相似
public class ConfirmOrCancelDialogFragment extends DialogFragment {
TextView tvDialogHeader,
tvDialogBody;
Button bConfirm,
bCancel;
private ConfirmOrCancelDialogListener mListener;
private String mTitle,
mBody,
mConfirmButton,
mCancelButton;
public ConfirmOrCancelDialogFragment() {
}
public static ConfirmOrCancelDialogFragment newInstance(String title, String body, ConfirmOrCancelDialogListener listener) {
ConfirmOrCancelDialogFragment fragment = new ConfirmOrCancelDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
args.putString("body", body);
args.putParcelable("listener", listener);
fragment.setArguments(args);
return fragment;
}
public static ConfirmOrCancelDialogFragment newInstance(String title, String body, String confirmButton, String cancelButton, ConfirmOrCancelDialogListener listener) {
ConfirmOrCancelDialogFragment fragment = new ConfirmOrCancelDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
args.putString("body", body);
args.putString("confirmButton", confirmButton);
args.putString("cancelButton", cancelButton);
args.putParcelable("listener", listener);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_confirm_or_cancel, container);
/* Initial Dialog Setup */
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); // we are using a textview for the title
mListener = getArguments().getParcelable("listener");
/* Link UI */
tvDialogHeader = (TextView) view.findViewById(R.id.tvDialogHeader);
tvDialogBody = (TextView) view.findViewById(R.id.tvDialogBody);
bConfirm = (Button) view.findViewById(R.id.bConfirm);
bCancel = (Button) view.findViewById(R.id.bCancel);
/* Setup UI */
mTitle = getArguments().getString("title", "");
mBody = getArguments().getString("body", "");
mConfirmButton = getArguments().getString("confirmButton", getResources().getString(R.string.yes_delete));
mCancelButton = getArguments().getString("cancelButton", getResources().getString(R.string.no_do_not_delete));
tvDialogHeader.setText(mTitle);
tvDialogBody.setText(mBody);
bConfirm.setText(mConfirmButton);
bCancel.setText(mCancelButton);
bConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onConfirmButtonPressed();
dismiss();
}
});
bCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onCancelButtonPressed();
dismiss();
}
});
return view;
}
}
confirmonceldialoglistener.java
这是您的侦听器实现,您可以随时添加更多内容,但只需确保它扩展了Parcelable,以便可以通过confiromanceldialogfragment.java中的newInstance方法中的包进行传递
public interface ConfirmOrCancelDialogListener extends Parcelable {
void onConfirmButtonPressed();
void onCancelButtonPressed();
}
使用示例:
这就是事情变得比我想的更混乱的地方。由于您的侦听器正在扩展Parcelable,因此您还必须重写这些方法,即DescripteBontents和writeToParcel。幸运的是,它们大部分都是空白的,而且一切都很好
FragmentManager fm = getActivity().getSupportFragmentManager();
ConfirmOrCancelDialogFragment confirmOrCancelDialogFragment = ConfirmOrCancelDialogFragment.newInstance
(getString(R.string.header), getString(R.string.body),
new ConfirmOrCancelDialogListener() {
@Override
public void onConfirmButtonPressed() {
}
public void onCancelButtonPressed() {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
}
);
confirmOrCancelDialogFragment.show(fm, "fragment_delete_confirmation");
这并不能完全回答您通过AlertDialogFragment传递它们的问题,但我认为如果这个问题这么长时间都没有得到回答,那么就值得给出一个如何使用自定义对话框完成任务的示例,这似乎让您对样式和功能有了更多的控制。如果您需要Kotlin版本,只需少量升级,请参阅:
class AlertDialogFragment : DialogFragment() {
companion object {
internal fun newInstance(
exampleParameter: String,
listener: AlertDialogListener? = null
) = AlertDialogFragment().apply {
this.arguments = Bundle().apply {
this.putString(EXAMPLE_PARAMETER, exampleParameter)
this.putParcelable(ALERT_LISTENER, listener)
}
}
interface AlertDialogListener: Parcelable {
fun primaryActionClicked()
fun secondaryActionClicked() { /* nop */ }
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) { /* nop */ }
}
const val EXAMPLE_PARAMETER = "example_parameter"
const val ALERT_LISTENER = "alert_listener"
}
private var listener: AlertDialogListener? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.dialog_alert, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
initListeners()
initExampleParameter()
}
private fun initListeners() {
val listener = arguments!!.getParcelable<AlertDialogListener>(ALERT_LISTENER)
if (listener != null) {
this.listener = listener
}
}
private fun initExampleParameter() {
example_view.text = arguments!!.getString(EXAMPLE_PARAMETER)!!
example_view.setOnClickListener {
listener?.primaryActionClicked()
dismiss()
}
}
}
您可能还希望忽略listener参数,以防您只需要将发生的事情通知用户。快乐编码 你需要一个包裹。创建者吗?不,你不应该需要一个包裹。创建者。上面的代码应该已准备好进行复制。请注意,此方法可能会导致问题。在设备上的开发人员选项中,打开“不保留活动”设置,确保返回使用此方法的片段时不会崩溃。通常,会引发异常,因为侦听器已不在内存中,并且没有创建者重新实例化它。任何可以序列化(可序列化或可打包)的对象都不应包含对UI对象的引用。此方法不鼓励使用,会导致错误。