catalinghita8 / android-compose-mvvm-foodies

Android sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM, Retrofit, Coil
470 stars 89 forks source link

[Improvement] Getting a result from the previous Destination #9

Closed JustJerem closed 3 years ago

JustJerem commented 3 years ago

You can remove the AssistedFactory for the viewmodel. Example :

EntryPointActivity.kt

   composable(
            route = NavigationKeys.Route.FOOD_CATEGORY_DETAILS,
            arguments = listOf(navArgument(NavigationKeys.Arg.FOOD_CATEGORY_ID) {
                type = NavType.StringType
            })
        ) {
            **val viewModel: FoodCategoryDetailsViewModel = hiltViewModel()**
            val state = viewModel.viewState.value
            FoodCategoryDetailsScreen(state)
        }

FoodCategoryDetailsViewModel.kt

@HiltViewModel
class FoodCategoryDetailsViewModel @Inject constructor(
    **stateHandle: SavedStateHandle,**
    private val repository: FoodMenuRepository
) : BaseViewModel<
        FoodCategoryDetailsContract.Event,
        FoodCategoryDetailsContract.State,
        FoodCategoryDetailsContract.Effect>() {

    **private lateinit var categoryId: String**

  init {
        **stateHandle.get<String>(NavigationKeys.Arg.FOOD_CATEGORY_ID)?.let {
            categoryId = it
        }**

        viewModelScope.launch {
            val categories = repository.getFoodCategories()
            val category = categories.first { it.id == categoryId }
            setState { copy(category = category) }

            val foodItems = repository.getMealsByCategory(categoryId)
            setState { copy(categoryFoodItems = foodItems) }
        }
    }
...

So you can delete :

 @Suppress("UNCHECKED_CAST")
    class Factory(
        private val assistedFactory: ViewModelAssistedFactory,
        private val categoryId: String
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return assistedFactory.create(categoryId) as T
        }
    }

And so, you can delete ViewModelAssistedFactory.kt and transform your activity for :

  ComposeSampleTheme {
                FoodApp()
            }

See official docs : https://developer.android.com/guide/navigation/navigation-programmatic#returning_a_result

I know that in this case, we use the information to bring the information back to a previous view, but since we have access to the backstack, we can also do that method here.

I saw it originally in a repo from Mitch Tabian. https://github.com/mitchtabian/Food2Fork-KMM/blob/6ab855181c76cab8ace282513efce2714b2a0b98/androidFood2Fork/src/main/java/com/codingwithmitch/food2forkkmm/android/presentation/recipe_detail/RecipeDetailViewModel.kt#L35

I can't create branch to make PR.

catalinghita8 commented 3 years ago

This is actually a great workaround. I like it because it will allow us to ditch all the assisted injection and simplify the whole codebase.

Thanks @JustJerem ! I will open a PR with these changes shortly and tag you there.

catalinghita8 commented 3 years ago

@JustJerem I have created the PR here. Let me know if it's fine so I can merge it and close this issue.