State Management in Jetpack Compose Best Practices - Android Studio Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys and welcome to the second video about State management principles in Jetpack compose in the first video we have talked about State hoisting and why it's actually so important and how to apply it in case you have missed this you can check this video by clicking this link above in this video we are going to talk about creating states by delegates with the equal sign if you should use mutable state or mutable State list of and all that kinds of creation State and also where you should actually put in your States if it's fine to manage the state inside a composable or if it would be better to create a separate stakeholder class like a viewmodel stage holder or composable stakeholder class and we will also make the state um surviving configuration changes so when the app is from portrait to landscape changed or even if the app's process is killed and it gets recreated all right okay I'm in Android studio and I've just created this example screen composable which holds a column and the text which says counter for now and the button without a functionality and the display text for the buttoner is increase so we want to increase the counter and want to display it and for that we need a counter State and let's have a look first why we need to always use remember when it comes to State insights a composable function we could say something like work Honda by mutable state of zero and let's not talk about this buy for now I will come to this very soon let's just know that this will create a state for us and we get a compiler Arrow here because the compiler already detects that we don't use remember here but let's silence the spawning with this Lin suppress and then we can see why I remember is so important because this example won't work if we want to display this calendar and in when we click on the partner we want to increase it so we could assume that we will have a counter which counts from zero up to as much as the button is pressed let's start this and have a look if we click on this increase then nothing happens this is because the state here is not remembered each time a button click occurs discount the variable will be increased but this will also cause the example screen compostable to recompose and since this is not remembered this calendar variable is always initialized with 0 again so this this will increase the counter from zero to one but immediately sets it back to zero and this is the problem here and this is is why we should use remember let's change this we say buy remember and copy and paste this mutable State up in here and then we can start the app again and have a look at the displayed calendar and now you can see the calendar increases appropriately all right okay let's talk about the Spy keywords what's the difference between the Spy keywords and this equal sign if we apply this equal sign then you can see that the counter variable can be increased anymore like this because if we have a closer look at this counter then we can see that a mutable state is wrapped around our integer we need to get the raw value so the counter dot value here which is our integer and then we can increase it if we would let it like this and print the counter here it will just print the objects and let me quickly show you this now you can see that there's an object which gets printed because it's not the direct integer value it's the object State objects and we always need to access the value when we use the equal sign because our calendar is now a mutable state of as you can see here mutable state is wrapped around the integer the only difference now if we use the by keywords instead of the equal sign is that this counter dot value call happens under the hoods we don't need to take care of it we delegate this call in general if we see the whole picture nothing changes we always need to use counter.value we always need to access the state's value and not the state itself but if we use the buy delegate here then this will be handled for us we don't need to take care of it this is just a syntactic sugar all right okay let's talk about configuration changes when our state is managed inside a composable like here we will remove this value call and increase the counter as we did before let's launch this and increase the counter by 5 and then we will apply a configuration change because right now this state won't survive a configuration change we can see this if we rotate the phone from portrait to landscape then the counter is zero again to avoid this and to make it even survive process kills and Recreation of the app we can use remember saveable let's launch the app again and then you will see that this works now if we increase the counter by 5 again and rotates the phone then you can see the counter is still five so always be careful if you manage the state inside your compostable this won't survive configuration changes if you just use remember use remember saveable for that the next thing I want to show is to use always remember with keys if you are depending on a value which could be changed let's create another composer I will simply call this test and this will take a text of type string this doesn't matter here if we say VAR text States by remember and we say here mutable State off and we pass this text all right then we have this text state but this will only be saved the first time if another text comes in if this composable gets invoked with another kind of text then this won't trigger again because this remember key is true by default I think and it does not trigger anymore if we pass through this is the same when we have some side effect handling here launched effect or something like this will also just trigger once if we pass through as a key we can pass text as the key and then this text state will be updated every time we get another text variable so if this text here actually changes then we will create another mutable State a new mutable State and update this text State accordingly this is just important to know maybe you fail something like this but normally you should also extract the state out of this test composable which I mentioned in the state hoisting video in the last video but maybe you face some situations which are like this and then yeah use remember with text of course or of course remember saveable which also takes these Keys here okay the next thing is list State Management because I have also faced this problem sometimes at the beginning and I wondered why my state isn't updating if we use such a list of maybe with two strings like this A and B and in here when we click on this partner we will say calendar okay well let's rename this to lists um and also um gets the first element of this list for example to display and if we then say list dot to mutable lists and we want to add an item we want to add this at the first index and we wanna say c for the item if we launch this then we could assume that's our car okay this is still called calendar and the rotation is also still applied and we have counter a actually because our list DOT first is a because of this list above if we now want to add something to this list to the Third position at index 0 and click on increase then nothing happens although we insert this element to this list and yeah as I already said I have experienced this my own and I wondered why this is not updating because it considers the whole list as a state so it only will be updated if the whole list changes and not single elements of it so if we comment this out and say something like this list is equal to a list of C A and B and if we launch this now then the UI will be updated with this new list and the C value which is the first index item will be displayed okay but how can we fix this with this um other approach if we want to update the UI when we just change a single element of the list we can simply change this mutable state of the mutable State list of and also remove this list off inside here and then we also get a compiler error because this does not have a set and get value we don't have a delegate here we need to use the equal sign we also need to remove this remember saveable because for such a list we need to provide a custom table and this would be out of the scope of this video but if you also want to make this state lists saveable during configuration changes then you should provide a custom saver down here we can change change this slide to list.at at index 0 with the character C if we launch the application again we will see that the UI will update if we add this item to the existing list you can see counter double Colon c okay with this approach we can also listen for State changes inside a list and not only when the whole list is created again or updated or something like this all right okay this was it for trading States different possibilities and so on now we will come to stakeholder classes which are very important when your composer builds just hold too much State let's imagine if you don't have just a list here you also have 10 variables and also a scroll States or a scaffold stage where you want to show different snack bars and all so on then you would have 100 lines of codes just for this date inside such a composable and for that we can use stateholder class and there are also different stakeholder classes we can create a composable as a stakeholder class or a view model which is a specific kind of stakeholder class okay I've removed the composibles from the previous example and added some State here we have for example a scaffold State a scroll state if we have some kind of list if we should show a confirm button or not is indicated by this state variable and we also have a calendar this comments here indicates that there can be even more States and as long as you don't have that much State like we had in the last example it's okay to manage the state inside the composable it's still clear it's still not too complex but if you have like this scenario with like 10 more State variables then this can be really confusing and if you have this case if you need to manage a lot of State then we should use so-called stateholder classes let's create such a stakeholder class normally I would put this in a separate file but for the sake of this tutorial we can do it down here this stateholder class will be a plain class we will call this example State and this class takes some arguments here we need our scaffold State and our scroll State because in here in this class we can't invoke this remember functions they can only be invoked inside a composable but later we will use a composable function to remember this example state so we can pass this scaffold and scroll States inside this example State for the counter we say this time bar calendar by mutable state of and say 0 by default we don't need to use remember here and we can't use remember because remember is also a composable function but we will later remember the whole example State class so there's no need to remember this single state variables if you have already created view models for State Management then you will see that this is kind of similar to view model but also a little bit different because this example States stateholder class is really only responsible for UI related stuff in the view model also accesses the business logic we will come to view models later but this is really only a UI State class which has only the responsibility to manage UI state or this should show confirm partner we could Implement something like this far or let's make this a well should show confirm partner of type Boolean and for the getter we will add counter greater than five this is also UI related logic we should show the confirm button if our counter state is actually greater than five and we also could add something like this show snack bar and we get a message of type string and in here we can then access the scaffold States dot snackbarhost stage dot show snack bar pass the message and we need a clear routine scope here yeah but let's not implement this here but just that you can imagine that we can all related UI stuff in here in this example stateholder class and we don't need to put it up here in our composable and we can make this composable only responsible for really showing the UI elements and this is a really nice separation of concerns here let's remove this again and implement the logic to access the example States inside our example composable we can use another composable for that and say remember Excel state in here we can create a scaffold state of type scaffold state is equal to remember scaffold State since we are are composable now we can invoke this functionality here and also the scroll state is equal to remember scroll States for the implementation of this composable we will simply say remember so we remember the example State and this is why we don't need remember for example for this calendar here we will say example State and pass the scaffold States and our scroll States and now we can go up here and remove all this state related stuff and we can simply say well example States is equal to remember example State like this and then we can access it in our example screen compostable for example example States dot should show confirmation partner and then we could show this partner or if we would have something like um functional snack bar with a message of type string then we could use it up here in our example screen composable we could use uh launched effects which only triggers if a specific value changes and on the initial compositioner here we can say examplestage dot should show confirmation partner and for the block we again need to check if the confirmation button should actually be shown because this will also trigger on the first composition of our example screen composable and in here we can then say examplestage dot short neckbar and since we get accuratine scope up here we can also make this a suspend functional and for example say scaffoldstate.neckbyhoststate.show snack bar and paste this message and then we can say you can confirm this now or something like this so we have been really nice and clean approach for different responsibilities and a nice separation of contents everything that's related to our UI state is in this example State stateholder class and this example screen is only responsible for displaying something on the UI all right okay this was the first possibility for creating stakeholder classes the second possibility are view models view models should be used if you also need to access the business logic and you need to update State depending on what you get provided from the business logic so you don't need necessarily all the time of your model if you are just interested in state that gets created by the UI on the initialization and if the user interacts with the UI and the state changes then you are also good to go with plain stakeholder classes I've done this by myself I've created a view model each time I needed state but this is not necessary it's only necessary if you need some kind of bridge between your UI and the business logic where you patch some data and want to update state or something like this but the cool thing is also that you can mix This Plane stateholder classes together with view models we could also have like something like this up here a well view model States is equal to viewmodel dot UI state or something like this and this state is related to the state that gets updated by the UI Sorry by the business logic and this is the plain UI State let's also quickly create a view model to have also an example for that we can say class example viewmodel and such a view model inherits from view model like this and of course I would also put this in a separate file in a real project but I think this is fine here in such a view model we can also create State like this while UI states by a mutable State off initial value for example we can also make this a private set which is a good practice so that we can only update the states inside our view model and we also don't need to use remember here because the viewmodel has a longer life cycle than a composable and it also survives configuration changes if you want to make this also survive process killed and Recreation of the app then you need to use safe State Handler but I won't cover this in this video because it's already quite long let's imagine that we have this init block and in here we will fetch some initial data in a view model scope so this is a security scope which can be used for invoking suspend functions because normally fetching data from a database or over the network are suspend functions if we would have access to a repository we could say repository dot fetch data and we could initialize our UI state with this and as long as this UI stage is not updated as long as that's disfetching it shows the initial value and after that it gets updated with the result of this fetch data and then we can go up here and say something like this well example view model of type example view model is equal to example viewmodel need to remove well here and normally in a real project we would also use something like dependency injection for this one but for the sake of Simplicity this is fine in here we will then say well view model States is equal to example viewmodel dot UI States and then we have access to our UI stage of the viewmodel where we want to show the current fetched value or the initial value and so we can mix up together this view model State and our plane stateholder class and this is very powerful and also a really really cool approach for separation of concerns our compostable is still only responsible for displaying UI elements this example state is responsible for only the UI related states which gets created by the UI which only gets updated in the UI and does not have anything to do with the business logic and our viewmodel state is all the state that's related with the business logic alright this was it for the State Management series and I think we covered a lot of things regarding State Management and Chad pick compose I have experienced so much clean code with this example it's with this approaches with State hoisting from the last video and also this kind of State Management and I don't have problems anymore with managing State and getting complex composables and all that stuff so I thought maybe this could also help you to build very clean composables and UI related logic
Info
Channel: K Apps
Views: 2,211
Rating: undefined out of 5
Keywords: State Management Jetpack Compose, Compose State, Compose State Management, Android State, Jetpack Compose State, State Hoisting, State Management, Jetpack Compose ViewModels, Android ViewModels, Jetpack Compose remember, Jetpack Compose mutableStateOf, Android mutableStateOf, Kotlin State Management, Jetpack Compose State Management, State Holder Classes Jetpack Compose, Jetpack Compose delegate, Jetpack Compose Best practices
Id: 2WAwKst4_sw
Channel Id: undefined
Length: 21min 19sec (1279 seconds)
Published: Thu Nov 10 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.