Side Effects & Effect Handlers - Android Jetpack Compose - Part 10

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome back to new video in this video i will talk a little bit about side effects in compose what they actually are and what we can do about them so essentially a side effect is just everything that escapes the scope of a function so for compose specifically that would mean everything inside of a composable function that does not have anything to do with compose so that could be something super simple as incrementing a variable that is not a state not a composed state but it could also be something like making a network call and putting such side effects into your composable functions is one of the worst things you can do in compose because we don't have control over our composable functions well we can define them but compose the compose framework decides when they are actually called so let's say you would make a network call in your composable function that would mean that on every recomposition and every ui update that network call would fire again and of course that is terrible you you don't want this but of course we still want to be able to make network calls to be able to access our database or just to increment variables that are not state so what we need is basically a safe environment where we can do these things and that's where so-called effect handlers come into play so compose already comes with a bunch of these handlers and i will now go through the most important of them and show you how they work so the most simple one is just called side effect with a side effect we basically have access to a block of code that is executed after every successful recomposition of our composable so let's just create a composable down here composible function my composable doesn't matter here and in here let's say we just have a button [Music] with an empty on click for now and we assign a text to that button that says click me now let's say for some reason we have a global variable here var i is equal to zero and for some reason we want to increment that i here inside of our composable but if we would just do it like this it would be considered a side effect and that is the bad practice here well if you simply increment a variable here um there is not too much that can go wrong um it could happen that the value of your variable is not what it what you expect it to be but it's not as bad as if you would do a network call here that would um on the one hand cause some network traffic every recomposition and on the other hand just take a lot of time but either way you really want to avoid putting such side effects into your composables and if you have to do them then you can use side effect and you can see that gives us a block of code and then we can put in our i plus in here and that will just now make sure that this block of code is called once this comp this composable successfully recomposed basically so after every successful composition if the composition fails for some reason this block of code is not executed and now sometimes you have a piece of code that requires some kind of cleanup after a composable basically finished composing and then we cannot use side effect instead what we need to use is called disposable effect so let's say we have our back dispatcher here which is just the dispatcher that is invoked when we click on our back button on our phone so just pass that here and imagine we would pass that from the outside and we would want to override the on back pressed callback here that is the example they use in the android documentation and i think it fits pretty well because it's simple so we would just create our callback here and use that in a remember block so it's not always re-initialized and here we can create that callback using object colon on back pressed callback we want to enable it and in here we can then override handle on back pressed and here do something and well if we would now use our back press dispatcher that we passed here and add a call back the callback that we created up here then we would add this callback on every recomposition but we don't remove it here so that would cause memory leaks which we want to avoid so that is another type here of side effect and because if we add a callback here and we want to remove it afterwards we need to use this disposable effect which is exactly for that need and you can see that now requires that we pass a key here and we will also see that key in upcoming effects i will show you in this video what this basically means is we can now we have to pass something now and whenever that something in our case our back dispatcher here back press dispatcher whenever that changes this block is basically executed our callbacks that we added previously are disposed and new callbacks are initialized so how that should look like now is we don't want to have i plus plus here instead we want to take our callback or add callback function put it inside of this disposable effect and now you can see we get an error here if we hover over this it says it's it required a disposable effect result but it found unit so what this disposable effects wants from us is this on dispose function and you can see that exactly returns this disposable effect result and this function is now triggered when these corresponding callbacks we added should be disposed so in here we can then use back press dispatcher dot um or is it actually back call back just call back dot remove yeah and here we can then remove the callback that we added previously so every time you just need to free up some memory some resources inside of a composable then you should use this disposable effect and now for the next effect i want to show you i will actually remove our composable here and also this eye and i will put that code directly into set content because then it's a little bit more clear i think so let's say we have a scaffold here and we create a state for that scaffold you already know that to be able to show snack bars remember scaffold state and then we pass that here for the scaffold state and then let's say we have some kind of state in here which is just a counter that we can increment when clicking on a button on our counter by remember and in here mutable state mutable state of zero initially and then simply use a button and when we click on that button we want to just increase that counter and we also want to give our button a little bit of text which just says click me and it displays the current count and now let's say if we launch this app then it's very simple i think you already guessed how that will look like we just have a simple button here and we when we click that we simply increase that counter but let's say we now want to display a snag bar if that counter is divisible by let's say five what we would then do is something like if counter modulo five is equal to zero and let's also say that the counter is greater than zero to not initially fire off that snack bar and in here we now want to show the stack bar which we can do with scaffold state.snackbarhoststate.show snackbar and just show hello and you can already see that gives us an error because show snackbar suspend function so we need to execute that within a croutine and you have also already seen this in this compose playlist where we used this valve scope equal to remember curtin scope which will just give us a curtain scope that is aware of this composition's life cycle so with that scope we can safely execute suspend functions inside of a composable by simply doing scope.launch and then putting in this line and if we now relaunch the app and then click our button here and when we are at five you can see the snack buff fires off when we are at 10 it will fire off again and when we click it a lot then these snack bars are basically enqueued and they will fire off one after another but let's say we actually don't want this that these snack bars fire off one after another let's say we have some kind of functionality that requires it that this scope here is cancelled when this condition is not true anymore and that is where a launch defect comes into play so that is another effect handler and we can just swap this scope.launch block out with launch effect and that will again require us to pass a key so whenever this key changes this launched effect will basically cancel the qrutin it runs in so that is basically inside of a croutin here it will cancel that and restart it so we can pass our scaffold state here dot snag bar host state and remove the block here and by the way we can also pass multiple keys as you can see here so if you want this to to also be triggered when other keys change then you can also pass more than just one so if we now launch our app again and then click our button okay now our sniper will display you can see and when we update it okay then it will immediately disappear because our curtain is cancelled so it will really only show when that number is divisible by five but let's actually get to my personal favorite one which i think i will use most often which is called produce state and that is basically built on top of this launch defect here and is in the end just syntactical sugar but what we can do with this is we can basically execute asynchronous code inside of a creatine and once that curating code that asynchronous code finished it will automatically parse the result into state and trigger our um or and we'll make our composable recompose so it will update our ui automatically when we get the result from let's say from our network call from a database request or so so instead of using this remember mutable state off here i will remove this and set our counter equal to produce state which we need to pass an initial value for so just the initial value of that state so this function will return a state um let's just pass 0 for that for that initial value and remove the producer and instead open this here you can see this gives us a produce state scope of type end because we pass an integer here for the initial value it now expects us to execute some kind of asynchronous code so that is inside of a crouton here and then after that we can just ask for state use a value and set that to the result of our asynchronous call so let's just delay this code for three seconds just for demonstration and then set the value to five or four then you can see that because this camera is now of type state of integer it doesn't recognize that counter as an integer and we can fix this by just appending value here as well and we cannot actually modify that counter now because it's immutable so let's just remove this on click listener here and write value here as well and if we now relaunch this app take a look here then after three seconds you will see okay then this number switches to four so initially this initial value here was assigned which is zero then it went into the screen it delayed the code for three seconds and after that it updated the value with four which caused this scaffold to recompose and just update all the composables in it that make somehow use of that state like this button text for example and that really makes many things super simple because you can just um if you make a network call you can set the initial value to some kind of loading resource just to indicate hey i'm in the loading state then you make your network call here and then you assign the result to either the the result of the network call or to some kind of error and then display that error in your ui accordingly or just display the result of the network call so i hope you like this video if so please leave me a like and also if you're interested in more advanced android premium courses check out the first link in this video's description which will lead you to my website where you will find these paid courses these are a way to support me and my work and also to bring your android skills to the next level i hope i'll see you in the next video again have an awesome day bye bye
Info
Channel: Philipp Lackner
Views: 6,112
Rating: 4.951952 out of 5
Keywords: android, tutorial, philip, philipp, filipp, filip, fillip, fillipp, phillipp, phillip, lackener, leckener, leckner, lackner, kotlin, mobile
Id: f_iIMscTNjQ
Channel Id: undefined
Length: 14min 28sec (868 seconds)
Published: Wed Apr 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.