THIS Flow Mistake Will Lead to Bugs in Your Code (StateFlow & Reactive Programming)
Flows are an awesome framework for reactive programming. However, to get the most out of them you have to understand the core concepts of reactivity. In this video I'll talk about some common mistakes.
⭐ Get certificates for your future job
⭐ Save countless hours of time
⭐ 100% money back guarantee for 30 days
⭐ Become a professional Android developer now:
pl-coding.com/premium-courses...
💻 Let me be your mentor and become an industry-ready Android developer in 10 weeks:
pl-coding.com/drop-table-ment...
Subscribe to my FREE newsletter for regular Android, Kotlin & Architecture advice!
pl-coding.com/newsletter
Join this channel to get access to perks:
/ @philipplackner
Join my Discord server:
/ discord
Regular programming advice on my Instagram page: / _philipplackner_
Checkout my GitHub: github.com/philipplackner
You like my free content? Here you can buy me a coffee:
www.buymeacoffee.com/philippl...
Пікірлер: 83
You actually showed the perfect reason to name the lambda parameters. Should be a good practice to not work with 'it'.
@s-w
Жыл бұрын
Yep, but I still use "it" when it's clear and there are no nested "its".
Phillipp, it would be helpful to us if you turned on `inlay hints` so we can see the types of your variable as opposed to having to manually select "type info"
As usual, great video, very informativ, well prepared and top quality. Thanks a lot ...!
Very informative, I dig the recent topics on the channel!
To add on, we can use a lot of methods for derived state in ViewModel like map, combine, filter, reduce, zip, fold, flatmap, etc as per the use-case.
this is fantastic. thanks for such amazing content Philipp. 🤝
Thank you for the tips as usual!
Great tutorial as always!!
mutableStateListOf() instead MutableStateFlow(emptyList()> unless I want to use sealed class ResultOf and get statuses for Loading, Error, Succes. Only in this case would I use Flows.
@PhilippLackner
Жыл бұрын
1. You can't assume someone is using Compose 2. Even for Compose, I don't recommend using Compose state in a VM directly. Will soon explain in a video why
@skarloti
Жыл бұрын
@@PhilippLackner class SnapshotStateList : MutableList, StateObject
@ChrisAthanas
Жыл бұрын
@@skarloti What is this snippet about?
@skarloti
Жыл бұрын
@@ChrisAthanas hello, maybe it will become clearer to you visually on the link I am sending you. I hope that's not a problem. The short demo shows how when data in a list is modified, it is updated in the user interface via MVVM. Take a look in row #22: snapshotFlow {} kzread.info/dash/bejne/hISkuruxp9KYqaw.html
An alternative to using combine and 3 different flows is creating just one, which could be represented by a single data class (wrapped in MutableStateFlow), which holds isLoggedIn, chatMessages and users. With this we can utilize the "update" method and only change the fields that require an update
Love your channel
Really Nice Tips. Thanks for this.
Great video. Thanks
Great video as always
Thanks for the great tutorial.
Awesome, thank you
This could be a good hint by IDE. When you are using state.value in operators like combine, suggest using that state in the dependents list Similar useEffect with useState in react.
Excellent, thanks. Would be interested in some practical use cases where other SharingStarted values are used.
I know Rx is not that popular now that flows are out there, but it would be great if you make a series explaining operators and how to combine them. Your ability to teach and the effort behind that is so incredible that learning such a painful topic as Rx might be, would make it easy to understand. Thanks for all your videos!
Best video really like your content 👍
thank you very much!
Awesome!
Thanks bro you are life saver
Mate, you are legend
Thank you
Thanks you Philipp 👍🔥🤟
@PhilippLackner
Жыл бұрын
Welcome!
I was making the same mistake.. I’ll get it fixed tomorrow as soon as I get my hands on that laptop
You keep giving me reasons to no longer use Compose States. Thank you.
combine is very usefull, I loved it 🤩
Love combine!
thanks a lot.
Also, as mentioned above, I tried to change flow value in a viewmodel and combine did not fired. It was only fires when items goes from repository for example
legend
you are the best
The old good transformation maps :)
Please make video on exoplayer with compose ui CONTROLS, eagerly waiting
@ChrisAthanas
Жыл бұрын
He has one, look for Spotify Clone
what's your studio's theme? looks pretty cool.
can you provide a tutorial about mutablestatelistof with jetpack compose
Hello, could you make a video about navigation with TopBar? I mean how to change topBar title and back button after changing our screen. In xml we can bind our toolbar to navgraph, idk how to do that on jetpack compose in right way.
Hi bro, please, make a video about the new logcat in AC)
Phillip, bc there was not a github link to the code, I wrote the code you have here into a project. The first example worked fine, but the second example (with the combine) only accepts the initial state for the chatState StateFlow. All additional `user.update{ it + user }` or `chatMessages.update { it + message }` do not emit additional ChatStates via the `combine`. It looks like this doesn't work as described. You should always run your code in these examples to be sure they are working as intended! It seems that the `combine` flow will not be re-triggered unless the values of the StateFlow variables change. Since the `List` does not change (only the contents of list change), the `combine` is never triggered. You will need to wrap the Lists and add a UUID (any random UUID) that indicates the underlying list has changed in order to trigger the `combine` to re-emit a new value. Thats the only way I could get this example to work.
@PhilippLackner
Жыл бұрын
I don't get what you mean, I just tried it again and the code is working perfectly fine as intended. A core concept of StateFlow is that it holds a value until it changes, so the collector will not fire until the chat state changes (which is what we want). So in your example, you might've changed the users or chat messages flow's values, but if that change doesn't cause a change in the ChatState (because you might've added a message without adding a user first), your collector will not be triggered. In either way, the combine block will be triggered with every update of the MutableStateFlows (if their value changes).
@ChrisAthanas
Жыл бұрын
@@PhilippLackner Im trying to figure out what is going wrong, because the code I have is the same as your code. I am collecting the `chatState` in the MainActivity (just like the first example), but when I call to the viewmodel to add a user or add a new message, (using an `users.update { user }` mechanism ) the `combine` is not triggered. Is there something special about the `collect` that is needed for the `combine`? Maybe you could include a link to your code so I can check out whats going on, because my code is identical to yours and its definitely not updating.
@ChrisAthanas
Жыл бұрын
I found a clue, it seems that the `combine` operator is executed on a looper, and if you don't give time for it to execute, you will not see the updates. The issue is that I thought it ran in the same coroutine/thread. When I launched the viewModel functions in a separate coroutine, the updates occurred, but they were batched together, so the collect would only see the latest state, not each individual state change, unlike the first example in the video.
@MyFoenix
Жыл бұрын
Yes, I also tried to change value of my flow in a viewmodel and combine did not fired
Phillip the G.O.A.T !!!
Why are you not using mutableStateListOf ?
What's the difference between map{} and mapLatest{} ?
Hi Phillip, please create a fresh Series of Android Development for beginners.. Please the Updated one..
Wow
Hi! Did you try to combine more then 5 values? When I tried I got an error about types...
@PhilippLackner
Жыл бұрын
at some point, you'll get an array of items since they don't want to create a million overloads of course
@MyFoenix
Жыл бұрын
@@PhilippLackner but in sorces varargs is used.... and this is popular case, complicated screens can use more then 5 flows...
@PhilippLackner
Жыл бұрын
@@MyFoenix yea but you get it as array
I tried exactly what you did in your example @Philipp, but it only updates the second flow (localUser) once, and every time I do something on the "_users" parent flow, the "localUser" flow doesnt get updated..
@PhilippLackner
Жыл бұрын
It's only updated if the result (the local user) changes
@pinoy_marites_beh
Жыл бұрын
@@PhilippLackner ohh, I see, I thought the premise was any updates "happened" on the "_user" , it will then automatically reflect (updates) to the "localUser"
@PhilippLackner
Жыл бұрын
@@pinoy_marites_beh add a println statement in the map block and you should see that it gets updated :) but the collector of localUser will only be called if the value changes
@pinoy_marites_beh
Жыл бұрын
@@PhilippLackner Still wrapping my head around when and where should I expect it to be updated though, maybe I'm thinking a different use-case, but anway, thank you Philipp, Great content as always.
why don't you just filter the list? instead of map and find?
@icycleragon
Жыл бұрын
Filter returns a list and he wanted a specific user
@PhilippLackner
Жыл бұрын
Filter would filter the flow, not the list. So with filter you could say that some list emissions are completely dropped
I would recommend passing the timeout as first parameter to SharingStarted.WhileSubscribed(), something like 2 seconds. this will ensure that the flow will not stopped and gets recalculated after screen rotation but instead it will stop if the app is in background.
in that last example, I don't understand why you say "Else we'd have to recalculate everything when any of the parameters changed". Isn't that what's happening anyways? Isn't there a way to also get WHICH of the combined parameters changed? We might be talking about a very long list, and I don't want to recompute the entire thing if another, unrelated variable changed which would only change the variable in an easy to compute way (imagine, it'd only change a color, not the value of the list, or something similar)
@PhilippLackner
Жыл бұрын
The problem you mentioned is what I was meaning. There's no way to detect that except for comparing the fields old and new value. You'd need to make each field a separate state flow then to detect that
@carlosmspk
Жыл бұрын
@@PhilippLackner Hah, I thought you meant that "combine" somehow solved that problem, and wasn't really understanding why. Thanks for clearing that up!
Does live data have anything like this 🤔
@PhilippLackner
Жыл бұрын
Yes, there are some transformations, but i haven't used it in a while. It's not as much as flows offer, which is also not the job of live data though (it's a state holder and not a framework for reactive programming)
But this isn't related entirely to flows, you are just stating the single responsibility principal, and avoiding coupling 2 variables in 1 function, isn't it?
@PhilippLackner
Жыл бұрын
No, this is not really related to SRP 😅 The video is about using flows correctly to avoid bugs and race conditions
u so handsome :*
I really like your videos, they are very informative, but could you please be aware of using 'actually', it happens too often.
@PhilippLackner
Жыл бұрын
I know I'm actually already trying 😂
Hi, Im fan of you from IRAN. People of IRAN need to theire voice heared. Please check the name #mahsa amini to figour out. Please be voice of iranians
Thanks a lot!
In the combine example, isLoggedIn, chatMessages & users have default values. They will never change. How to make them get data from database?