androidmvvmandroid-jetpack-composeclean-architecture

Clean way to share data between viewModels


I'm trying to follow Google's clean architecture guidelines.

I have a navigation subgraph with multiple pages corresponding to stages of filling a form.

Each page has it's own viewModel.

On the last screen I need to send data from the form to app's data layer which sends it to server.

How should I share the form object between viewModels?

I see such options here:

What should I do?


Solution

  • Use a ViewModel scoped to the Navigation Graph (per subgraph) AND delegate logic

    How to do it:

    1. Create a FormViewModel scoped to the navigation subgraph (not individual screens).

      • This acts as the shared state holder.
    2. Each screen still uses its own ScreenViewModel, but it reads from/writes to the FormViewModel.

    3. Validation and retrieval logic stay in screen ViewModels.

    4. Only FormViewModel talks to domain layer when submitting the final form.

    // Shared ViewModel scoped to the subgraph
    class FormViewModel @Inject constructor() : ViewModel() {
        var formState = mutableStateOf(FormData())
        fun updatePart1(data: Part1) { formState.value = formState.value.copy(part1 = data) }
        fun submitForm() { /* call useCase to submit */ }
    }
    
    // Each screen has its own logic
    class Step1ViewModel @Inject constructor(
        private val formViewModel: FormViewModel // Injected via navGraphViewModels()
    ) : ViewModel() {
        fun onNext(input: Input) {
            // validate and update shared state
            formViewModel.updatePart1(convert(input))
        }
    }
    

    Navigation-Scoped ViewModel:

    val formViewModel: FormViewModel by navGraphViewModels(R.id.formGraph) {
        defaultViewModelProviderFactory
    }