У меня есть простой класс:
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();
}
}
Теперь мне нужно напрямую нажимать кнопку "слушать" в SimpleDialogFragment
, потому что я не могу передать слушателей через Bundle
(args). Но я хочу - так он будет выглядеть как экземпляр AlertDialog
:
AlertDialogFragment dialogFragment = new AlertDialogFragment.Builder()
.withTitle(R.string.no_internet_connection)
.withMessage(messageId)
.withPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).build();
dialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_NO_INTERNET_CONNECTION);
Но теперь я должен установить слушателей таким образом:
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);
Возможно, установка на кнопки щелчка непосредственно на экземпляр DialogFragment
вместо передачи через аргументы Bundle
небезопасна, так как рекомендуемый способ передать аргументы Fragment
передаёт их через аргументы Bundle
.
И я знаю, что рекомендуемый способ общения с Fragment
в Android - обязать активность хоста для реализации интерфейса обратного вызова. Но это не ясно, что Activity должно реализовать этот интерфейс до тех пор, пока ClassCastException
не будет запущен во время выполнения. И это также делает сильную зависимость - использовать ее где-то вне Activity. Я должен реализовать интерфейс Callback
в Activity. Поэтому я не могу использовать его в Fragment
"независимый" от хоста. Действия: prepareAlertDialogFragment().show(getActivity().getSupportFragmentManager(), "tag");