architecture-samples icon indicating copy to clipboard operation
architecture-samples copied to clipboard

"TODO-MVVM-RXJAVA" Snackbar message is not shown.

Open Sevastyan opened this issue 7 years ago • 3 comments

"TODO-MVVM-RXJAVA"

createTask() method of AddEditTaskViewModel.java is calling showSnackbar() when the user is trying to create an empty task. This snackbar is ignored, because of the immediately following .doOnCompleted(mNavigator::onTaskSaved) that finishes the Activity and never lets the Snackbar to appear.

Sevastyan avatar Feb 13 '18 07:02 Sevastyan

the bug is caused by the order of RxJava operations in AddEditTaskViewModel.java.

What’s happening In TODO-MVVM-RXJAVA, the createTask() method probably looks something like:

private void createTask(String title, String description) { if (title.isEmpty()) { mSnackbarText.setValue(R.string.empty_task_message); return; }

mTasksRepository
    .saveTask(new Task(title, description))
    .doOnCompleted(mNavigator::onTaskSaved) // finishes the Activity
    .subscribe();

} Problem: When the user tries to create an empty task, showSnackbar() (or setting the LiveData/ObservableField for Snackbar) is called — but in the normal valid path, .doOnCompleted(mNavigator::onTaskSaved) runs immediately after saving and finishes the Activity, hiding any Snackbar instantly.

In the empty-task path, there might also be a subtle Rx chain where the Snackbar call happens before .doOnCompleted, so the Activity is closed before the Snackbar is even rendered.

How to fix it The fix is to only navigate away after a successful save — not when validation fails.

Option 1 – Move validation outside the Rx chain

private void createTask(String title, String description) { if (title.trim().isEmpty()) { mSnackbarText.setValue(R.string.empty_task_message); return; }

mTasksRepository
    .saveTask(new Task(title, description))
    .doOnCompleted(mNavigator::onTaskSaved)
    .subscribe();

} Here, the Snackbar path never triggers .doOnCompleted, so the Activity stays open.

Option 2 – Filter the Rx chain If you really want to keep everything reactive:

Observable.just(new Task(title, description)) .filter(task -> { boolean valid = !task.getTitle().trim().isEmpty(); if (!valid) mSnackbarText.setValue(R.string.empty_task_message); return valid; }) .flatMap(task -> mTasksRepository.saveTask(task)) .doOnCompleted(mNavigator::onTaskSaved) .subscribe(); Now, .doOnCompleted() only runs if the task passes validation.

Why this matters Right now, users never see the Snackbar for empty tasks because the Activity finishes too quickly.

Moving validation before the save logic ensures the UI remains visible so feedback can be shown.

Also improves UX consistency with the MVP versions of the sample.

VaradGupta23 avatar Aug 08 '25 12:08 VaradGupta23

Thanks, but I don't care anymore after 7.5 years 😄

Sevastyan avatar Aug 08 '25 12:08 Sevastyan

Haha, fair enough! After 7.5 years, sometimes you just gotta let it go. 😄

VaradGupta23 avatar Aug 08 '25 12:08 VaradGupta23