Dear Android colleagues from Google, current state management in compose is nuts. It feels like the API changed gazillion times just in the past 2 years, and today it feels like only you guys understand what the hack is going on in there.
I am rewriting our java+kotlin+xml project to Compose. So, what I can say... despite I experienced developer it seems that modern recommended android development is very over complicated especially for beginners... All these: lifecycle APIs, flow, state flow, compose state, APIs for getting one from another , many helper wrappers around such APIs..., Hilt, viewmodels as holders for business, and UI logics .... Looks like some mess and need to be rewritten totally 😁. Just one example of bad arch IMHO. In fragment world recommended approach is to use navcontroller or plain supportfragmanager and *replacing* one fragment by another when we want to show new fragment. Viemodel here is for storing data from backstacked fragment. But instead of replacing previous fragment we could just hide it! (view is still live in container, just hidden) and show new fragment above (view add to container). That is use .add instead of .replace method with some tricks of hiding all previous. The same behavior was implemented for Activities before fragments! Why you changed this by suggesting replacing fragments? When we use add/hide approach we no need viewmodels at all;), because view is still live and when we go back we just see what was on a screen before without any new requests of data. Simple to use.
Your idea/approach doesn't take into consideration how the Android System manages these view components., that is Application Lifecycle. When you add an activity over another, the system places the activity in a state where it no longer consumes resources. However fragments don't work that way. They will continue to use resources even if the user is not viewing the fragment. So if you don't "replace" instead of "add", the fragment is just sitting there consuming RAM when it doesn't need to. It's better to replace, and save your state (Viewmodel or onSavedInstance). However onSavedInstance should only save simple data. That is, data that can be QUICKLY serialized and deserialized. Otherwise you risk stuttering (like most badly designed apps where they don't consider lifecycle states). This is where the Viewmodel comes in. It survives configuration changes, can hold complex and bloated data types/objects, outlives your fragments and works with your app's lifecycle, and decouples data holding & management from Activities and Fragment (which they shouldn't. They should just present). They are also more entwined with your lifecycle if you use Kotlin StateFlows.
You don't have to integrate every single one of those APIs. I'm also a beginner Android developer myself (though not a beginner with programming in general), and the simple apps I've created so far haven't used things like Viewmodels, Hilt, flow, or any of those you mentioned. You can start with the basic building blocks which Compose provides (like basic remember + mutableStateOf, or navigation compose with a navController). And then you can add the other features depending on the complexity of your app, current need, or as you go along So it's all about understanding the tools and why you use them, not just blindly throwing everything into your project
I think numberOfRolls should be taken from roll object instead of user inside the combine function (18:07). Otherwise this state will get missing in case the screen went to the background more than 5 seconds. Unless you cache it after every roll. And I'd reduce user to StateFlow before passing it to combine to avoid showing loading after 5 sec in background.
@@manuelvicnt Sorry for the late reply, thank you so much. That makes perfect sense and this is a great article. (There are so many great new articles! 😁)
based on recommendation at 8:19, if we would have to pass `resources` to viewmodel, is it better to pass `applicationContext.resources` instead of Fragment resource?
Well, this is hard to answer. On one hand, you should stay away from using anything context related as said. And I would advise against it. On the other - from R+ it is recommended to fetch resources via Activitys context because Applications context could report wrong values for multi-window and secondary displays. (Fragments resources just get one from the activity). What do you need it for?
Hi! You definitely can use it if the UI state is the screen UI state is created using local sources of state change or one-shot APIs. See my reply in Trevor's question in this video for more information about this. Thank you!
@@manuelvicnt hello Manuel, just one question about fragments. Modern navcontroller and old plain supportfragmanager uses .replace method when we want to show new fragment. It's recommended approach. Previous view is destroyed, fragment is putting to backstack. Viewmodel for this fragment holds data and responsible for reattach data again to new view when we go back to this fragment. But there is another approach working with fragments which I saw in many big and popular apps. It's not destroying view , not replacing fragments, just hidding previous and showing new. That is you hide prev frag and show new one. Both view are in container. Benefits: views are not destroyed. When we go back to previous fragment we just show it and that's all! We no need to reattach data or request data again - fragment and view is still live and just showing... I saw some implementations on GitHub. They are not so complex. Also it gives you option to use fully custom animation based on views, also getting results from new fragment to previous using simple callback (like in iOS), because previous fragment and it's view is still live! What do you think about this approach? Ps: this behavior was implemented for Activities before fragments - one activity is opened just above previous.
The data layer should not contain ANY business logic IF we are using a Domain layer. The data layer should ONLY be concerned purely CRUD operations and ALL business logic should be in the Domain layer where Usecases hold all the business logic and the domain layer does not depend on any other app module. This is Clean Architecture which enforces a separation of concerns. I can't think of any reason why you would develop an application where you would mix concerns of data persistence with business logic ALL within the data layer. This is plain wrong.
No offense (I am just trying to make a suggestion), Please Sir let others explain the stuff, your voice is not suitable for lecturing, every time I watch your videos I learn lots of stuff but at the same time I get headache. Plz let others do the speech part
I feel the opposite, when others explain in perfect English I understand absolutely nothing, when Manuel explains it, I perfectly understand what he says.
I've been waiting for a detailed talk about States 🤩, Knowing the different options available for us will help a lot!
We're very happy to hear this, Charfaoui! Thank you for the feedback, and we're glad the video was helpful 😁
@@AndroidDevelopers
Dear Android colleagues from Google, current state management in compose is nuts. It feels like the API changed gazillion times just in the past 2 years, and today it feels like only you guys understand what the hack is going on in there.
This talk has answered so many of my questions thanks Manuel!
hi, thank you! Please, give an example of managing viewmodel complexity with delegates as described, I want to see it in detail
super important talk and issues to mention. thanks a lot
You're very welcome! Don't forget to also check out the video description for even more on this topic 😊
I am rewriting our java+kotlin+xml project to Compose. So, what I can say... despite I experienced developer it seems that modern recommended android development is very over complicated especially for beginners... All these: lifecycle APIs, flow, state flow, compose state, APIs for getting one from another , many helper wrappers around such APIs..., Hilt, viewmodels as holders for business, and UI logics ....
Looks like some mess and need to be rewritten totally 😁.
Just one example of bad arch IMHO. In fragment world recommended approach is to use navcontroller or plain supportfragmanager and *replacing* one fragment by another when we want to show new fragment. Viemodel here is for storing data from backstacked fragment.
But instead of replacing previous fragment we could just hide it! (view is still live in container, just hidden) and show new fragment above (view add to container). That is use .add instead of .replace method with some tricks of hiding all previous.
The same behavior was implemented for Activities before fragments! Why you changed this by suggesting replacing fragments?
When we use add/hide approach we no need viewmodels at all;), because view is still live and when we go back we just see what was on a screen before without any new requests of data. Simple to use.
Your idea/approach doesn't take into consideration how the Android System manages these view components., that is Application Lifecycle. When you add an activity over another, the system places the activity in a state where it no longer consumes resources. However fragments don't work that way. They will continue to use resources even if the user is not viewing the fragment. So if you don't "replace" instead of "add", the fragment is just sitting there consuming RAM when it doesn't need to. It's better to replace, and save your state (Viewmodel or onSavedInstance). However onSavedInstance should only save simple data. That is, data that can be QUICKLY serialized and deserialized. Otherwise you risk stuttering (like most badly designed apps where they don't consider lifecycle states). This is where the Viewmodel comes in. It survives configuration changes, can hold complex and bloated data types/objects, outlives your fragments and works with your app's lifecycle, and decouples data holding & management from Activities and Fragment (which they shouldn't. They should just present). They are also more entwined with your lifecycle if you use Kotlin StateFlows.
True and real. My patience is running thin with all these bs
You don't have to integrate every single one of those APIs. I'm also a beginner Android developer myself (though not a beginner with programming in general), and the simple apps I've created so far haven't used things like Viewmodels, Hilt, flow, or any of those you mentioned. You can start with the basic building blocks which Compose provides (like basic remember + mutableStateOf, or navigation compose with a navController). And then you can add the other features depending on the complexity of your app, current need, or as you go along
So it's all about understanding the tools and why you use them, not just blindly throwing everything into your project
I think numberOfRolls should be taken from roll object instead of user inside the combine function (18:07). Otherwise this state will get missing in case the screen went to the background more than 5 seconds. Unless you cache it after every roll.
And I'd reduce user to StateFlow before passing it to combine to avoid showing loading after 5 sec in background.
Do external streams of data have to be exposed as a cold flow always? For example a state in the data layer that's fetched from a local database?
What is that "Success" type in the stateless DiceRollUI composable function's when statement? Shouldn't that be DiceRollUiState.DiceRoll?
@18:50 Any resources on pros and cons of StateFlow vs Compose State and reasons for that decision?
@@manuelvicnt Sorry for the late reply, thank you so much. That makes perfect sense and this is a great article. (There are so many great new articles! 😁)
based on recommendation at 8:19, if we would have to pass `resources` to viewmodel, is it better to pass `applicationContext.resources` instead of Fragment resource?
Well, this is hard to answer. On one hand, you should stay away from using anything context related as said. And I would advise against it.
On the other - from R+ it is recommended to fetch resources via Activitys context because Applications context could report wrong values for multi-window and secondary displays. (Fragments resources just get one from the activity).
What do you need it for?
Thanks very
Why not use mustableStateOf instead of MutableStateflow in ViewModel
Hi! You definitely can use it if the UI state is the screen UI state is created using local sources of state change or one-shot APIs. See my reply in Trevor's question in this video for more information about this. Thank you!
@@manuelvicnt hello Manuel, just one question about fragments. Modern navcontroller and old plain supportfragmanager uses .replace method when we want to show new fragment. It's recommended approach.
Previous view is destroyed, fragment is putting to backstack. Viewmodel for this fragment holds data and responsible for reattach data again to new view when we go back to this fragment.
But there is another approach working with fragments which I saw in many big and popular apps. It's not destroying view , not replacing fragments, just hidding previous and showing new.
That is you hide prev frag and show new one. Both view are in container.
Benefits: views are not destroyed. When we go back to previous fragment we just show it and that's all! We no need to reattach data or request data again - fragment and view is still live and just showing...
I saw some implementations on GitHub. They are not so complex. Also it gives you option to use fully custom animation based on views, also getting results from new fragment to previous using simple callback (like in iOS), because previous fragment and it's view is still live!
What do you think about this approach?
Ps: this behavior was implemented for Activities before fragments - one activity is opened just above previous.
Nice info but really hard for understanding by start class developers
Good talk! We only let our VM talk to our use cases in our clean Arch.
620
This is so complicated...
Peace.
The data layer should not contain ANY business logic IF we are using a Domain layer. The data layer should ONLY be concerned purely CRUD operations and ALL business logic should be in the Domain layer where Usecases hold all the business logic and the domain layer does not depend on any other app module. This is Clean Architecture which enforces a separation of concerns. I can't think of any reason why you would develop an application where you would mix concerns of data persistence with business logic ALL within the data layer. This is plain wrong.
No offense (I am just trying to make a suggestion), Please Sir let others explain the stuff, your voice is not suitable for lecturing, every time I watch your videos I learn lots of stuff but at the same time I get headache. Plz let others do the speech part
his accent is thick
I feel the opposite, when others explain in perfect English I understand absolutely nothing, when Manuel explains it, I perfectly understand what he says.
Tech is very international - you should be used to working with many different accents
Sorry this doesn't feel intuitive at all. You should learn more from swiftui...
No mention of SavedStateHandle.getStateFlow(), we're back in 2017 making people think ViewModel alone is enough for handling process death 🤦