Kotlin Coroutines Tutorial (STABLE VERSION) - async / await, withContext, launch

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
with catalan 1.3 when you finally have a stable library for co-routines this means that there won't be any breaking changes to their api and now it's also an especially good time to learn how to use them kuru teens are basically lightweight and much more efficient threats as a bonus they are extremely easy to work with once you know the basics asynchronous co-routine code looks the same as a classic synchronous code which we are all used to you don't need to learn any new programming paradigms in order to use cotton score routines hello welcome to resew coder in this tutorial you are going to learn quite a bit about color things different ways of launching them blocking versus non blocking code and async/await with context and more so let's get started even though I am demonstrating co-routines on a plain cotton project I will notify you whenever there is something which is Android specific so after watching this video you can jump straight to your Android app and implement co-routines without a problem so I am using IntelliJ we are gonna start a new project with Gradle and select Kotlin Java to be the language for our project hit next I'm just gonna say co-routines and the same for the artifact ID and yeah we should be good to go now because catalan 1.3 is not officially out yet we need to go over to tools up here so tools then Kotlin and now configure catalan plug-in updates and you will probably have something like stable and we need to change this stable to be early access preview 1.3 if you are watching this video a bit later than it was recorded 1.3 will be already out because at this time it's already release candidate as we can see over here is one point 3.0 RC so it's going to be coming out in really short time but for now just change it to early acts preview if you haven't already next up we want to go over to the build a Gradle and over in dependencies we need to add this line over here and you can get the code from the link in the video description so we don't need to type out all of this just click on link and it will take you to resew coiler comm co-routines in catalan are not a part of the language but they are rather a library and this line of Gradle code imports this library over to our project so cotton Xcode routine core as you can see in the version we are using something like zero point three point one EAP 13 over time once the Kotlin 1.3 is not only release candidate but it's the full version already this version of Catlin xqo routines will jump to 1.0 0.0 but for now because we are only using a release candidate of Catlin we need to be using this EAP version of cotton Xcode routine score over at this link which is in this comment above the compile this is the link where you can find the most up-to-date versions of co-routines library and this thing will obviously be also in the video description so now let's hit import changes all right now let's start writing code so let's go over to main and Kotlin we want to create a new cotton file and let's call it just main and it's going to have a main function which looks something like this alright so usually when you write code you write something like brain line for example just to keep this simple and you print out one then you can also print line so ctrl D to duplicate it below and it's going to print too and then also 3 and if we were to run this it would obviously print out 1 2 3 this is called synchronous code because it runs one after another which is called synchronous but let's say that over here this middle prin line will have some kind of a long-running hard computation to do and only then it will print to once the computation is finished so let's create that kind of function right now so it's going to be fun and we aren't going to really do some crazy calculations we are just going to delay the execution of the code by using a really nice function called delay so we're gonna call this function print line delayed and it's going to take in a message of type string and here would be your complex calculation but for now we just wanna put some delay over here so in classical threading that would be threaded steep so for for example 1000 milliseconds and then we would print line with the message which was passed into this function right now just so we are in writing everything inside the main function I'm gonna create a separate function and paste the contents of the main function over there and its name will be fun example blocking so then after watching this tutorial you can go over to the link in the video description and get all of the code from there for further reference and let's paste what I just cut from the main function over here but this print line too will now be a simple print line but print line delayed and now from the main function let's call example blocking and let's run our code so hit this green play button next to the main function and as you could see down here at first it prints out one then it waits for a second and then it prints out two and three and this is using classical threads but we don't want to be using threads we want to be using co-routines so we are going to change this thread dot sleep to call delay and it's gonna delay for one and milliseconds as well and as you can see up top we have automatically imported Catlin xqo routines delay and also we have an error saying that suspend function delay should be called only from a KO routine or another suspend function so what we need to do is to write suspend before this fun and what this does is that it makes this function suspending and this is a really awesome feature of co-routines they don't block the current thread like the thread that sleep does so delay is not like thread that sleep it only suspends this particular suspending function so if there is some code over here write some code over here this code runs then it hits delay it suspends the execution the program is still running everything is not blocked and once the delay is finished it will come back to this precise place and it will run whatever the code is below this KO routine call and obviously you aren't gonna probably use delay in production but you will have some kind of a really complex calculation this time for real and I am going to show you how to put your calculations inside co-routines in just a little bit alright but now we have another error which is over here that prin line delayed is also a suspend function just like delay is a suspend function so we need to either make this function suspend and we could do that but now check this out we have a problem over in main so even main should be suspend but we cannot make everything suspend something actually has to be non suspending for example his main function will be non suspending in our case so how are we going to deal with calling co-routines from some code if not everything can be suspending well we are going to delete this spent keyword and we are going to say that this spring line delayed should run blocking right and now we are going to put this spring line delayed over to this block of code which will run blocking and in the documentation we can read that runs new co-routine and the blocks in bolt it blocks the current threat interrupts ibly until its completion so run blocking is actually really blocking the threat so it's pretty much simulating the thread that sleep there are also other options which aren't blocking the current threat to which we are gonna get in just a little while but for now let's stick with ROM blocking so run blocking provides us with a co-routine scope so basically this means that we can call suspending functions from run blocking and block of code now when we are going to run the main function it will print out one right and then after a second two and three just like before but now we are doing it all through core routines there is also a more idiomatic way to write this blocking co-routine code and that is to put run blocking to be basically the root of this function so run blocking over here and it's gonna do the same thing as when the run blocking was just around this print line delayed but it is much more nice to look at and we can test it and sure it one prints one and then after a second it prints two and three awesome now let's make one more example with run blocking and I am going to paste that in here alright so over here we have run blocking and we have something called dispatchers the default when we provide a dispatcher to a core routine it will switch to a different threat most of the time but even though this run blocking block of go here we'll be running on a different thread so not on the main thread but on some kind of a another threat it will still block the main threat because we are using ROM blocking so now let's call this example blocking dispatcher from our main function and let's run the code so we have one and then two and three over here one printed that it's from thread default dispatcher worker one then two is also from default dispatcher worker one but we had to wait for one second between 1 and 2 because 2 is printing the light so it only prints something out after 1 second delay and only after this run blocking which was by the way running on a different thread but it was still blocking the main threat because only after this run blocking back of code has run only then this third line of code which brings out 3 ran and it said that it's from a main thread all right now let's create another function example launch global so it's also going to have run blocking as the route and over here we also want to print one from thread at the start of this function but then we want to use launch function on global scope so global scope the launch and over here in this launch we want to print delayed just like above so we're gonna paste it in here and what this launch will do is that it doesn't block the main thread you will see what that means once we run this code but for now we want to have a narrow line over here which will say print line 3 just so you can see how this code is executing and now let's copy the name of this function let's paste it inside our main function so that it runs and let's hit run so we get 1 and then 3 and we don't get 2 so what's up with that well it's not that this prin line delayed is now called it is called but precisely because it is delayed the the entire program stops before this delayed function could be executed because it prints 1 then it launches print line delayed but it's waiting for one second but it after a few nanoseconds it starts printing 3 because launch is not blocking so it's just continuing the execution of the code so it prints 3 and then our program thinks all right I'm I'm done here let's quit this but the program is not done here it still needs to print the two but it doesn't know that it should print 2 because it doesn't know that it should wait so we need to explicitly tell it to wait for a certain period of time so let's hit delay and for example for 3000 so that it's really noticeable and now when we run our code it's still going to print out one three and then two and after three seconds it's going to finish executing so just to recap this 2 could be now printed out precisely because we are waiting so we are explicitly blocking the main thread and because it's blocked it registers this printing this delayed printing of our 2 because print line delayed is waiting for 1 second before it brings out the message all right now let's copy this example launch global and paste it below and I'm going to change its name to be example launch global waiting and what are we going to wait for well this delay is really ugly and it's not a good practice because if you have some kind of a variable length of the delay so when you are not just delaying but you are actually running some crazy commutation inside your function over here you don't really know how long that calculation will take on some machines it can take one second and on some machines get take like 100 milliseconds right because of that you need to be able to wait just for this launch to finish executing and nothing more we can do that so we can wait for this launch to be fully executed by putting the return value of launched inside the job right so while job is equal to this loan because as we can see over here it returns a job and then instead of delay we can call a job that join and this is something like delay but it waits for the job to finish and then it quits the program as soon as possible so now let's copy this and paste it over to main and I'm going to actually collapse all of these previous functions so that they aren't interfering with us so now we are joining the job and when we run the program now it will still print one and three then two and it immediately stops it doesn't wait any longer than it really needs to all right so now let's copy even this function and paste it below and let's collapse the first one and this one's name will be example launch co-routine scope so we are not gonna be launching in the global scope but we are going to launch in a local color teen scope as you can see over here run blocking provides us with this which is of type co-routine scope as you can see over here so what we can do is to delete this global scope right and we are going to launch this on this cover teen scope not on global one but we could also write this that launch which is pretty much the same so we are gonna launch on the local cover teen scope of our run blocking co-routine what this will enable us to do is to delete this job that join because we don't need to join anything more because now that we are running this launch on local co-routine scope our program will know that oh I should probably wait for there one second before stopping the program so that this two can be actually printed so let's copy the name of this function paste it over to main and let's run it and it's gonna do pretty much the same thing as the code before but now we aren't explicitly waiting for this job to finish the compiler is spitting out code that does precisely that but we don't need to do it ourselves and as you can see all of these calls are from the main thread and just like run blocking can accept dispatcher launch can also get a custom dispatcher asked to it so let's pass it right now so let's write dispatchers default right and now when we run the code the two will be no longer printed from the main thread but from default dispatcher worker 1 then it's there is also high o dispatcher but it has shared threats thread pool with the default dispatcher so even though we are using io here it still runs on default dispatcher worker one but IO dispatcher is more suited towards Iowa operations so disk IO Network IO because it can rapidly spin up multiple threads then we also have another dispatcher and that is main over here and unconfined should not be used from your code as you can see here note use with extreme caution not for general code and when people over at Catlin say something like that I am respecting them fully so I'm now going to touch and confine dispatcher because if they suggest that it's not for general code I'm going to trust them but we have this main dispatcher and when we run this it's actually not going to run because over here it says module with main dispatcher is missing add dependency with required main spatula cotton X co-routines Android and you can immediately see that this main dispatcher is intended for Android or for some kind of other rich UI framework as you probably know over on Android you can only change the contents of a textview so for example textview that text is equal to hey right you can only do that from within the main threat which can operate on UI you cannot do anything like that from some kind of an outer thread so whenever you want to run a core routine so that you don't get your main thread blocked but you still want to do something like this where you are operating with the UI you want to use dispatchers that main over on Android and that will enable you to actually operate with UI so keep that in mind over at Android you should always use dispatchers that main when you want to do something with your UI but if you don't have Android cars on xqo routines you cannot use this patters DUP main because it is not available and as a bonus I am going to show you how you can create your own custom dispatcher so we can create a new executor service so but we are going to put it inside the dispatcher so let's first create a custom dispatcher and it's gonna be equal to executor z-- that new fixed thread pool and you can also do something else so new single thread executor or something like that but I'm going to use new fixed thread pool over here and I'm going to have two threads and then let's call as co-routine dispatcher this is an extension function from our cartoon exco routines called library and it's going to simply turn this executor which is used for normal threading and it's going to convert that to a Colt in dispatcher and now we can use our custom dispatcher inside our launch so custom dispatcher and now let's hit run and now we get one three and two and this time it's not from dispatchers main one or something like that it's from pool one because it's our custom new picks thread pool right but as you can see there is something not all right the program didn't stop executing and when I run it once more you can see that we have this instance but we have also in our instance of the program still running so what's up with that well it turns out that with a custom dispatcher the program doesn't exit execution because the custom dispatchers thread is still running we need to manually shut down the custom dispatchers executors to stop the threat so let's go down here and we want to write custom dispatcher that executor and we want to cast this executor to be an executor service and then we want to call shut down on this executor service now let's close all of our programs which are currently running and let's hit run again and now we get one three two and we also get this processed finish with exit code zero so now we are good to go and not waste system resources calling launch returns a job which we can join either explicitly or implicitly when we are using a local co-routine scope but it doesn't return a value and most of the time however you want your cover team to return a value and now just some kind of a job for example data fetch from the server or the result of a long-running calculation that's where a sink and a wave and also with context come into play so let's collapse this function and we're gonna create a new one called fun example async await so also run blocking also over at the top let's create an error suspending function calculate hard things and it's going to get one start numb of type integer and it's going to return also an integer and over here we want to delay for one millisecond so also delay one or now one millisecond by one second so 1000 milliseconds right and then we want to return start num timestamp right so we are returning a value from calculate hard things but we didn't return anything from print line delayed now let's go down to our example async/await and how are we going to get this return value from calculate hard things in quarantine and then propagate it outside of the cover team this is a bit of a problem but thankfully Kotlin solves that problem for us with async so we are going to create Val the third one and it's gonna be equal to acing and then this async block of code will call calculate hard things and we are gonna pass in ten and then we could immediately call a weight so here a weight and it would basically for now block the threat because we are inside run blocking co-routine and once this calculate her things would stop running after one second it would continue with whatever the code is below but async and a weight are really well suited for running multiple things concurrently because we want to have also another vow deferred so let's copy and paste below is going to be the third two and is going to oh man the star dam will be twenty right and then also the third three and the start Nam will be thirty and if we were to call away it a weight and a weight after each and ever Racing this block of code will run 3,000 milliseconds because calculate her things runs for a second because we are delaying the execution by 1000 milliseconds however because we are using a Singh we can await all of the results of our racing functions at once so let's do just that we are going to create vowel sum and it's going to sum every single deferred so the third one that a weight plus the third first to that weight and also plus the third three that weight and then we are going to print line async/await result and the result is equal to our sum right and just so that you believe me that this code doesn't run for three seconds but for less I'm going to create vowel start time over here and it's gonna be equal to system that current time Milly's in milliseconds right and then also end time down here and I'm going to print line saying that time taken to execute this whole function is n time - start time so now let's copy the name of this function and let's paste it above in main and let's run our code now and we get a single a result is 600 but more importantly the time taken for this whole example a single weight function is only 1028 milliseconds which is basically a second so this means that we are running all of our async concurrently because every calculate hard things call takes one second and they are taking place concurrently at once and not sequentially as they would be if we called a weight after each and every async immediately right we call await then so let's check it out right so we delete a weight from our the firts when we are summing them up and now when we run our code it's not going to take only 1028 milliseconds but it's going to take something like 3,000 milliseconds right so let's run this let's wait and you can already see that it's taking much longer and yeah as you can see the time taken now is 3000 and that is not good because we can just as easily run it in only 1000 so let's revert our code back to 1000 and let's check it out again just so that we know that it's still working in the end I would stake in 1025 so async and the weight are really cool but sometimes we don't need to run multiple things concurrently but we still don't want to block the threat for that there is the with context and I'm going to show you how to use it right now but first let's copy the function example async/await because our with context function will be really really similar so let's rename it to example with context instead of the third one the four two and three we're going to have result one two and three that's because async is returning the firt on which we can await however with context doesn't return the firt but it returns directly whatever is coming out from our calculate hard things and in our case that is an integer so let's rename them to result all right and now let's change a Singh to be with contacts and we need to specify the color T in context explicitly for with context so let's just say dispatchers that default for now and let's change every a Singh to be with context now we cannot await on our results so let's delete a wait and as you can probably tell with contacts is basically the same thing as when we were calling a weight after each and every async it does the precisely same thing and when we copy the name of this function and run it you can see that it took 3,000 milliseconds approximately the core takeaway from these last two examples is that you should use async when you want to run multiple calculations or something else concurrently so when you want to wait for multiple things at once and that will enable you to run these a things concurrently which will save significant amount of time however when you have some one-off operations or some other operations which you just don't want to run concurrently you should use with contacts because it's simpler to write and it is designed for that for waiting for the result immediately alright and that's it for this tutorial if you want to get the code go to the link in the video description which is gonna take you to reso coder com if this video helped you to understand cuddling score routines give this video a like and also share it with others subscribe for more tutorials and also Android tutorials like this and also hit the bell button so that you are actually notified about those videos leave a comment if you have any suggestions or anything else to say follow me on social media see you in the next video [Music]
Info
Channel: Reso Coder
Views: 70,695
Rating: 4.9465055 out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, kotlin, kotlin tutorial, kotlin 1.3, kotlin coroutines, kotlin coroutines tutorial, kotlin coroutines 2018, kotlin coroutines explained, kotlin coroutines example, kotlin coroutines suspend
Id: jYuK1qzFrJg
Channel Id: undefined
Length: 32min 52sec (1972 seconds)
Published: Sat Oct 06 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.