catalinghita8 / android-compose-mvvm-foodies Goto Github PK
View Code? Open in Web Editor NEWAndroid sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM, Retrofit, Coil
Android sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM, Retrofit, Coil
BaseViewModel:
private val _viewState: MutableState = mutableStateOf(initialState)
val viewState: State = _viewState
@composable
private fun FoodApp() {
val viewModel: FoodCategoriesViewModel = viewModel()
val state = viewModel.viewState.value
Any changes to value will schedule recomposition of any composable functions that read value. In the case of ExpandingCard, whenever expanded changes, it causes ExpandingCard to be recomposed.
here dont hava remember,why it can to be recomposed?
i think it is :
val state by remember{
viewModel.viewState.value
}
but no remember,it can be recomposed.
Hi,
Really like the implementation but I am struggling to find a way how to test view models. To be precise, how you would assert all values set to compose State<T>
instance. Any ideas?
Aren't you sending the previous state? ๐ค
I can make it work if I use:
override fun setState(state: () -> ViewState) {
_viewState.value = state.invoke()
}
or just _viewState.value = state
. Maybe I'm missing the point ๐
There is a small issue with background color in dark theme becaus of usage of the same color for background both in dark and light pallete. See below image:
Home | Detail |
---|---|
![]() |
![]() |
I changed the background color for dark pallete so it looks like this
Home | Detail |
---|---|
![]() |
![]() |
Are you fine with this? If so i will open new request.
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.
private suspend fun getFoodCategories() {
setState { setIsLoading(true) }
val categories = repository.getFoodCategories()
setState {
copy(categories = categories).setIsLoading(false)
}
**delay(2_000)**
**setState { setIsLoading(true) }**
setEffect { FoodCategoriesContract.Effect.DataWasLoaded }
}
I'm trying to change the state information but this doesn't work if a delay is applied.
delay(2_000)
setState { setIsLoading(true) }
But the effect is well applied for this line.
setEffect { FoodCategoriesContract.Effect.DataWasLoaded }
Do we know why ?
All in all, good job for this architecture.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.