I've been trying to determine if it's possible to create an observable DialogFragment
. Essentially I want to be able to:
DialogFragment
Observable
which can be subscribed to for the result (ok/cancel pressed, String input, background task success/failure, etc.)So far the closest thing I've found is ReactiveDialog
, which used to be part of RxAndroid, but has been removed from RxAndroid in v1.0.0 as a part of simplifying RxAndroid.
While ReactiveDialog
does appear to meet my first two criteria, it does not appear to handle configuration change. There are two issues to consider:
DialogFragment
must maintain its Observable
across configuration change so it can notify subscribers of its state.I'm still fairly new to RxJava, so I'm still trying to wrap my head around how you would manage something like this. It seems like it should be possible, but I feel like it would require a static or singleton Observable
manager and possibly retainedInstance
DialogFragments
.
Anyone have any suggestions or best practices for this?
There are two issues here; one is that you don't want to lose Java Objects during relayout - look into the runtime changes docs about that.
The other issue is that you want to create an Observable that has the action of the dialog, when that action is triggered. For that, have a look at the RxJava docs, the Asynchronous Observer example. You will need to create an Observable.OnSubscribe
, and pass that Subscriber
to your code that will call the necessary onNext
/onError
/onCompleted
calls.
I would use a ViewModel for the dialog which helps with configuration changes. After a configuration change re-subscribe to the dialog's ViewModel.
SimpleActivity
public class SimpleActivity extends AppCompatActivity {
private SimpleDialogViewModel dialogViewModel;
private CompositeDisposable compositeDisposable;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialogViewModel = ViewModelProviders.of(this).get(SimpleDialogViewModel.class);
compositeDisposable = new CompositeDisposable();
showDialog();
}
@Override
protected void onResume() {
super.onResume();
Disposable disposable =
dialogViewModel
.actionStream()
.subscribe(
result -> {
if (AlertDialog.BUTTON_POSITIVE == result) {
// User clicked yes
}
if (AlertDialog.BUTTON_NEGATIVE == result) {
// User clicked no
}
}
);
compositeDisposable.add(disposable);
}
@Override
protected void onPause() {
super.onPause();
compositeDisposable.clear();
}
private void showDialog() {
SimpleDialogFragment dialogFragment = new SimpleDialogFragment();
dialogFragment.show(getSupportFragmentManager(), SimpleDialogFragment.TAG);
}
}
SimpleDialogFragment
public class SimpleDialogFragment extends DialogFragment {
public static final String TAG = "SimpleDialogFragment";
private SimpleDialogViewModel dialogViewModel;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dialogViewModel = ViewModelProviders.of(getActivity()).get(SimpleDialogViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_simple_message, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
final View btnYes = view.findViewById(R.id.yes);
final View btnNo = view.findViewById(R.id.no);
btnYes.setOnClickListener(v -> dialogViewModel.onClickYes());
btnNo.setOnClickListener(v -> dialogViewModel.onClickNo());
}
}
SimpleDialogViewModel
public class SimpleDialogViewModel extends ViewModel {
private Subject<Integer> actionSubject;
SimpleDialogViewModel() {
actionSubject = PublishSubject.create();
}
public void onClickYes() {
actionSubject.onNext(AlertDialog.BUTTON_POSITIVE);
}
public void onClickNo() {
actionSubject.onNext(AlertDialog.BUTTON_NEGATIVE);
}
public Observable<Integer> actionStream() {
return actionSubject;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With