It's crazy how often your videos come out when I most need them. Thanks!
@abdelrahmankhaled7575 Жыл бұрын
I like these type of videos which does not directly teach a new concept but rather opens a discussion on a special topic this made me understand the topic better in deep, thanks for this, and hope for more videos of this type !
@AlexGnok Жыл бұрын
We actually have used another workaround for this - the old school Event class with isConsumed property. So the ViewModel sets the state (StateFlow), then the Fragment during consumption first checks if the Event has been consumed already (in which case just ignores it), then if not - does what it needs to do and sets the property isConsumed to true. This combined with some extension functions (like consumeIfHasntBeenAlready and peekContent for testing) makes a flawless job
@ПавелКуликов-ж9н Жыл бұрын
Thank you so much for your videos. I’m writing a diploma work in my university using Android development, I have never worked with mobile applications and I’m really love clean architecture, so your videos about MVVM, about Jetpack compose, comparison sharedFlow, channels, QR-codes, cameraX, AI and so on are GREAT. So maybe it’s just simple word “thanks” for you, Philipp, but you should know, that this “thanks” for me is COLOSSAL THANKS! I’m from Russia and our developers on KZbin don’t talk about all of this as good as you! So don’t stop making this very useful and meaningful videos, you are great)
@PhilippLackner Жыл бұрын
Thank you! All the best for your diploma 💪🏻
@etasdemir Жыл бұрын
Great video, thanks! one thing to add for 7:00 channel's default capacity 0 which used in the video and it creates a rendezvous channel. Publisher suspends itself until there is subscriber or subscriber suspends until there is a publisher.
@DenisFisenko Жыл бұрын
Awesome video, thanks! We use state way for one-time events. To unify the handling of such events we've created a common interface like: interface UiEvent { val data: T val onConsumed: () -> Unit }. Where the `onConsumed` callback is set to the view model's function to set event property in the state to null. With some nice extensions, handling of such events on the UI layer is uniformed and clean.
@PhilippLackner Жыл бұрын
That's awesome, thanks for adding 🙌
@Narazgul Жыл бұрын
I like this solution as well, in case I'd have to stick with state
@riyupapa39 Жыл бұрын
That is also good idea. If the event is not happen continotly like snackbar text or some of notify , MutableState with reset consume also good.
@LokendraBohara-s3u5 ай бұрын
how to use this . any example
@nicoloagnoletti3275 Жыл бұрын
Crazy to me how hard it is to make junior colleagues understand the difference between state and one-time events Great content as always 👍
@gustavobarbosab Жыл бұрын
I agree with you Philipp... When we are using "Channels", the code is simpler to understand, and thinking about junior developers, working with states in this situation can be hard and generate a lot of bugs. This kind of thought about right and wrong depends on the context. Nice video, thank you for sharing your knowledge with us.
@satnamsingh-qh2si3 ай бұрын
I used state to trigger & Observe event in my Jetpack compose project and I can say it was a pain in as*** as most of the time I forgot to reset the state back after it's single use.. So thanks Philipp for having this video on youtube to guide people like us. Thanks a lot...
@amzpakistani3186 Жыл бұрын
Hey Philipp, excellent work! Can you please make an updated tutorial about ktor and Rest API? I would really appreciate that 🙏
@SerhiiSolodilov Жыл бұрын
The only issue is that rotation isn't the only reason to lose event. If you consider that ViewModel could be recreated too state will be on top of the solutions list.
@PhilippLackner Жыл бұрын
In which scenario would the ViewModel be recreated, but not the UI?
@SerhiiSolodilov Жыл бұрын
@@PhilippLackner UI also wont exist. Example is when the user start operation, switches to another app and Android decides to kill your app. When user get back, ViewModel needs to be restored and show correct UI and having state is more suitable for that.
@PhilippLackner Жыл бұрын
@@SerhiiSolodilov ah now I see what you mean, yes that is a good point
@ernestguevara5968 Жыл бұрын
I saw the use of channels first in your form validation video and it blown my mind, because first I was using events then unknowingly has the same implementation as manuel, but I didn't like it for the same reason that I need to reset it everything, for me it looked dirty. So when I saw the channels in your form validation video, I replaced it and works and look what I want it to be!
@dahlola Жыл бұрын
Very nice video! I have been battling with how to implement one-time events and ended up following Manuel's advice because I wanted to stay on the safe side. But I agree that it introduces a lot of complexity and one junior developer in my team doesn't really understand it. I myself can forget about resetting the state also. But now I feel more comfortable using channels and think I will switch to that :)
@kotasjn Жыл бұрын
I dealt with this dilemma for several weeks last year and I'm glad I ultimately stuck with the same solution that you did. If you have a solid understanding of channels and can handle them correctly, there's no need to use state for single events. 👍
@walkmn Жыл бұрын
Sounds like we are still in process of finding best mechanism of doing one shot event from viewModel to UI
@pelealexandru Жыл бұрын
thanks Philipp for the deep dive on the topic! i'm working on a greenfield project with compose and i was really not sure how to best handle this kind of viewmodel driven navigation scenario. i fully understand the options now!
@verbranntenetzhaut Жыл бұрын
Hey Phillip I subscribed to your channel a while ago because I got really interested in Android content but I stopped watching your videos because they just weren't that great presented compared to reading a blog article etc. Now I just want to give some positive feedback because this video is very good, referring to the blog article, preparing an example that demonstrates the different cases and keeping it all readable was very helpful. Your insights and POV are very valuable, thank you for the effort and I'll definitely tune in more often 👍
@ssSFrankSss Жыл бұрын
This is a thumbs up video from me. After creating some complex apps I am entirely aligned with your position on this topic! Keep up the good work ;-)
@TuanBuianonymous Жыл бұрын
Wow, i have been wait too long for video like this. Thankssssss
@nem1st Жыл бұрын
I was waiting for this video for so long. Thank you very much!
@mohammad_droid7 ай бұрын
Perfect! I was a fan of the sharedFlow school, but you convinced me as usual😂
@samadMahmoodi Жыл бұрын
there is no RIGHT way to do ANY thing in android
@sina28624 ай бұрын
yes people just care about funectionality and performance of the app , they dont care for example you used jetpack compose or xml or native drawing
@__J____ff4 ай бұрын
oh shut up junior ! stop encouraging antipatterns. There is a proper way to do something, thats why we have different things like stateflow or sharedflow.
@DayZilya Жыл бұрын
I loved the video. Would love more of such content. Explaining differences of approaches
@phuang326 күн бұрын
Thank you for the full demonstration on this. It's clear and helpful.
@Otabek001uz Жыл бұрын
Very nice, it's amazing, good luck Phillip!
@stanchostanchev5991 Жыл бұрын
All this sounds very nice, but how these constructions will behave when we set "Don't keep activities" to ON in Developer options, which will make activity to be recreated every time when we bring test app from bg to fg. This will illustrate how the app will behave after the device goes to "doze" mode.
@bitwisedevs469 Жыл бұрын
First! Finally this topic! Indeed, resetting state which is being suggested by many can cause more bug when someone forgets it instead of sticking to use channel. Thanks a lot
@aldaricJohnes Жыл бұрын
channel are really bad for that, the second your app will be killed by the system you will have an inconsistent state between your state and channel, and that's way worse than "someone forgetting" Design errors are worse than dev errors
@bitwisedevs469 Жыл бұрын
Fair enough, actually that is what we are doing currently. However if this is the case then all we need here is to use StateFlow directly so no need to convert Channel to state. Unfortunately manually resetting each state is making it hard to maintain and it adds more complexity to read the system flow. So this approach is where we are heading.
@Nixomia Жыл бұрын
Your videos have been incredibly helpful, and I really appreciate you sharing your knowledge. I recently tried to put your Jetpack Compose tutorial into practice while building an app, but I'm having trouble with the login/register navigation and home nested navigation. Specifically, I'm unsure how to manage the scaffold for the login and register screens, and I'm also struggling to customize the FAB for each screen in the home nested navigation. Any guidance you could provide would be greatly appreciated.
@valentinvolodarskij Жыл бұрын
Thanks for a video on a really interesting topic but I have one question about LaunchedEffect. I have seen in many examples that we have to pass the lifecycle as a key to close the LaunchedEffect if the owner of the lifecycle has changed. But do we really need to pass it as a key? Because according to the documentation the LaunchedEffect will be closed and restarted if one of the keys changes OR the LaunchedEffect leaves the composition. So in general we will only close and restart this effect when the activity has recreated itself (which means that the LaunchedEffect will leave composition even without lifecycle as a key) or I don't understand other cases where the lifecycleOwner is changed Thanks in advance to everyone for any clarification on this question! :)
@leonardomiranda13499 ай бұрын
Excellent video, you explained every scenario flawlessly 👌
@riyupapa39 Жыл бұрын
This is very very very important and powerfull tip!!!!!! Thanks Philipp!!!!
@AlejandraStamato3 ай бұрын
Brilliant video on a topic full of nuances, nice one :)
@omkarpawar1741 Жыл бұрын
why does android not provide a simple and optimal way to develop apps, instead of focusing on core development of what features our might need, developers have to worry about what to use for development, there are so many permissions to handle that it has become crazy, then with compose state and viewmodel, in viewmodel satetfllow, sharedflow, and the list goes on, and the pace at which these changes come makes all the code developed earlier redundant
@PhilippLackner Жыл бұрын
I agree, but I think it's also incredibly easy to say that and hard to do. Making everything safe for users, easy for developers, easy to use for users, run as fast as possible is very complex and a lot of interests clash together. If developers would have a much more limited toolkit which is simpler to use, they'd again complain why they don't have fine grained control. It's just hard to please everyone to the fullest degree.
@Naxomiun Жыл бұрын
You dont need to use all these tools. In fact they are pretty useless if you know what are you doing. Most of these things can be replaced by common and 'old' patterns, which didnt have these problems btw
@omkarpawar1741 Жыл бұрын
@@Naxomiun using old tools has the advantage of their reliability but there is always a risk of google deprecating them and bringing out half baked or totally different tools, the way SAF(Storage Access Framework) was handled then the epic moment when deprecations were deprecated and then brought back, now in compose handling a simple variable or an UI state is just a joke, compose state, view model, they could have just brought one viewmodel api and managed the one time events more effectively, some thing which has to baked in the OS itself is left to the developers, like handling denial of permissions with no Propper out of the box solution where developers have to provide their own logic, instead on working on a new feature for their app , imagine developing an app requiring camera from a service using notification where images and video permission are to be handled for api 32 and lower, api 33 and then api 34 and higher. wonder if the various teams developing different apis within google even communicate with each other where different "features" end up being a problem for developers
@Naxomiun Жыл бұрын
You will always be able to use bare threads instead of coroutines, service scoped classes instead of viewmodels, callbacks instead of flows or hand dependency injection instead of Hilt. Theres no way no one could ever deprecate those as they are part of the language. In fact, the possibilities of viewmodels/livedata/etc being deprecated are really high if you know about google historic changes in its APIs.
@PedroBarbosaRoman3 ай бұрын
Regarding the article solution, if we are sending events (by updating the compose state object) with a high frequency (milliseconds) doesn't it drop some of them? Since the compose rendering system drops the intermediate states and only considers the last one for the recomposition.
@deepakkanyan1072 Жыл бұрын
Today only I was working on same functionality, really thanks its really helped
@manticomar1146 Жыл бұрын
I don't care what the other dude from Google says for me. philip is always right. We respect u philip
@unknownBoy85lover Жыл бұрын
Thank you it will helpful absolutely great value to your videos and sharing your experiences with us ❤❤❤❤
@sriduttan7692 Жыл бұрын
Hey @PhilippLackner , Awesome video, thanks! I have a Qn, WhileSubscribed function takes stopTimeoutMillis. can't we just set stopTimeoutMillis to 5000ms for ex. this will address all the issues when lifecycle/orientation changes happen. it will wait for the collectors to come back, therefore emissions won't get dropped. (StateFlow)
@Guilo583 Жыл бұрын
It is amazing. I always learn new thing when watching your video. Thanks
@jeyhey5320 Жыл бұрын
For somebody who has always used a state-solution, anything else seems odd. Of course you need to handle state reset because it is a state. You can’t get around it no matter what you do. You also need to think about it in the other solutions.
@ahmetozcan2278 Жыл бұрын
What about keeping a list of ui events in the state object and update the list when the events are processed ?
@TheRcfrias10 ай бұрын
For some reason, the channel option will just be "collectable" once, as well as emitted once. I was hoping I could have 2 different isolated views react to this channel through the viewModel, but only the first view that collects the event will get the "message". I am switching back to state, since this is proven solution for precisely this scenario.
@PhilippLackner10 ай бұрын
What you're looking for is a sharedflow as the name says :)
@TheRcfrias10 ай бұрын
Memory-wise, is there any difference, improvement, best practice to pick sharedflow instead of state in a view controller? Are you saying sharedflow will also emit once, but can be heard by several views and not just one?
@PhilippLackner10 ай бұрын
@@TheRcfrias correct, it's like a channel that allows multiple subscribers
@mariuskohmann8476 Жыл бұрын
Great video! How does SingleLiveData from LiveData lib compare to these solutions using Flow/State?
@andreasrichman5628Ай бұрын
I was just wondering for something like Event Bus what is the most suitable approach do you think?
@theophilus494 Жыл бұрын
wisdom!!! thanks always Philipp
@sina28624 ай бұрын
its be great if you create a app like music player or chat app and do your best approaches for each senario
@nikolozlatsabidze2196 Жыл бұрын
what can you suggest for state inside viewModels. data class or sealed class. consider the case when ui is very complex, data classes become very big and complex with lots of parameters. is it the sign to use sealed class or even decompose it using another viewModel. so may be multiple viewModels for that particular screen.
@mobiledevpro Жыл бұрын
Thanks you shared you thoughts about that . Well-explained👍
@redaelmadini Жыл бұрын
What if we have to send multiple events at one (in a list)? I think the third solution with "state" is most suitable. Plus, in some scenarios we have to later consume this event after an action, i.e undo delete action within a snack bar that we have to keep after rotation.
@eddieng7136 Жыл бұрын
Would you talk about the new compose Multiplatform wizard ?
@mesutemrecelenk5447 Жыл бұрын
Hi Phlipp. Thanks for this nice tutorial. How to use observeAsEvent function for our all composables?
@codingCouncil Жыл бұрын
What about collectAsStateWithLifecycle ? . We can't provide the dispatcher.Main.immediate there can we ?
@codingCouncil Жыл бұрын
anyone wondering how to provide Dispatchers.Main.immediate with collectAsStateWithLifecycle; this is how val uiState by viewModel.uiState.collectAsStateWithLifecycle(context = Dispatchers.Main.immediate)
@rakam.a8070 Жыл бұрын
What's the difference between collecting state with MutableStateFlow and MutableSharedFlow? I usually use MutableStateFlow but I see other people use MutableSharedFlow as well, which one is recommended?
@PhilippLackner Жыл бұрын
SharedFlow is NOT state, it doesn't cache anything by default. As the name says, only use StateFlow for state
@adrian110288 Жыл бұрын
The difference between the two is mainly in a way they behave upon subscribing to them. I think official docs explain it well, you can then decide which behaviour suits your case better 👍
@ChrisAthanas Жыл бұрын
Super useful breakdown of a controversial and misunderstood factor of Andriod and pure compose apps
@dawidhyzy1425 Жыл бұрын
Would be nice to hear Manuel Vivo response too 🙂
@evgeniy2012year Жыл бұрын
great video! Events look like the best option. thanks
@Slodin5 ай бұрын
I really disliked the ui state thing with cleanup work. I often have to test a screen many times and oops forgot to clear a state and now it's debugging time. I have been using that pattern, but I run into bugs so often that I's annoying. Which is why I got here I guess. Is there really no downside to this approach tho? it seems like everything we do will sacrifice something in order to achieve something else. If it's just some performance then I would happily give it away as most applications I make are not intensive. Having a less buggy approach beats any performance hit IMO (as long as it doesn't renders the app unusable).
@1stCyborgOnMars Жыл бұрын
Great video. Thanks for helping again
@nowfarhan Жыл бұрын
Can you skip events when you use sharedflow with repeat=1? If you are using it for events, I think this is the easiest solution.
@vitalijuskolinko9011 Жыл бұрын
replay = 1 is equivalent of StateFlow :) You will be able to go back then.
Жыл бұрын
Very well explained Phillip
@yeminnaing71973 ай бұрын
Thanks! Now I do understand very well .
@jaysh1175 Жыл бұрын
Nice video, but to be honest I kinda fell over the argument against state being: "You always need to think about resetting the state [...] when I think of a larger team where the might be junior developers as well [...]" and then proceed to add the Dispatcher.Main.immediate which is equally 'not obvious' (or even worse) in my opinion
@PhilippLackner Жыл бұрын
Yes, I agree that the immediate dispatcher isn't obvious either, but it's a single rule that has to be established in the team ("when observing events, ALWAYS use this ObserveAsEvents function"). Resetting state is not so trivial, since it sometimes need to be reset and sometimes it's fine to leave it (such as when the previous backstack is cleared after navigation). Even though, I knew the mechanism behind resetting state, it happened to me more often than not that I forgot it. Especially, because one-time events on Android are almost always handled with channels/SharedFlows in Android projects, using state is a rather uncommon approach which is why I think this concept would be new to 95%+ of junior devs and would require an additional intro
@hnim2292 Жыл бұрын
how about use StateFlow with Event class?
@meetb26 Жыл бұрын
if Mutable StateFlow and live data use so problem
@alexeysimchenko7494 Жыл бұрын
I definitely prefer a State to use
@yuuzuX Жыл бұрын
If using presenter to update the ui?
@GulshanRahimova Жыл бұрын
Great video
@mikeshilovski1512 Жыл бұрын
Great videoo, thanks 👍
@LEEJIHUN Жыл бұрын
필립 센세 항상 감사합니다
@breensrobert Жыл бұрын
this was insightful
@MajesticNut5 ай бұрын
But the Channel's buffer by default is 0...
@MonichGPT Жыл бұрын
You just need helper container with nullable field
@龔詩測試機1號 Жыл бұрын
Nice topic bro
@frajola_br Жыл бұрын
Good morning, do you have a video teaching how to mask input? I didn't find any tutorial teaching how to mask phone number, or even currency
@danieldawson8018 Жыл бұрын
cmd + f, my friend. ;)
@aamirhoda73634 ай бұрын
Phillip, I'm just blown away by the amount of knowledge you have & your ability to deliver that knowledge in such a precise & to-the-point manner that probably a 10 year old can also understand perfectly fine. Superb, thanks a lot, massive respect, unlimited love! 💙💙💙💙💙💙💙💙💙💙💙💙💙💙💙 BTW, just a funny note, at the end of your video, you could have done that counter check on the best-of-3 condition because previously you had to do that two times to validate your point 😅😅😅😅
@noider545 Жыл бұрын
Incredible.Wonderful.Exceptional.
@androidpc96563 ай бұрын
COMpose
@ka61er Жыл бұрын
:v i always use the third way
@TheFlexath3 ай бұрын
thank youuuuuuuuuuuuuuu
@HelloWorld-xt8wp Жыл бұрын
Excellent video. But isn't a coroutine context in viewmodels and in views already Dispatchers.Main.Immediate? I do not understand how this hack works.
@stoyan_vuchev Жыл бұрын
I've got a notification about the video exactly when I was about to implement a navigation channel! Coincidence? I think NOT! 😂Thank you Philipp for the amazing content, keep up the Great work! 🙌🏼 Here is a quick snippet of the function to observe such events in a lifecycle manner: @Composable fun CollectFlowWithLifecycle( flow: Flow, lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, onCollect: suspend (T) -> Unit ) = LaunchedEffect(flow, lifecycleOwner.lifecycle) { lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { withContext(Dispatchers.Main.immediate) { flow.collect(onCollect) } } }