Android Code-Along: Kotlin coroutines

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

So he says if we mark room dao method with suspend or retrofit one then we can call if from main coroutine dispatcher and it will switch to some thread. I wonder about 2 questions:

  1. Does this magic work with the Flow? If we started a flow from the main and didn't change with .flowOn() at any point, will room switch it by itself?
  2. Does this magic work only when the coroutine dispatcher is Main?
👍︎︎ 6 👤︎︎ u/Evakotius 📅︎︎ Mar 10 2021 🗫︎ replies
Captions
hey everybody and welcome to our very first andray colon I'm Karen engineer on the Android Developer Relations team Hi, everyone. I'm also an engineer on the developer relations team. Thank you so much for joining us today in this Andre Courtland series we will be live coding different programming challenges you will face as you progress as an Android developer so here we are so that you can get a better understanding of how we recommend approaching those challenges Yeah so as menos coding along I feel free to pull back in the Studio and also follow along or you could feel free to just watch and do the Colab yourself a little later. We're also going to be looking at the live chat. So if you have any questions, feel free to ask it in the live chat and we'll try to answer as many questions as we can. Thank you so much. So the first topic for this series is going to be carotids so I'm going to be calling here on my laptop so please feel free to go along with me or actually with us and ask as many questions as you have will be very happy to answer them. So we move to the laptop here I hope it's being shown right time Yep Yeah and we already have a great question coming in so Zina's is this going to be for someone who knows nothing about coroutines Yeah, definitely joinder right. So we are going to assume nothing so basically we're going to start from scratch assuming that you have some sort of Android background here like a little bit what we are trying to achieve things like what happened when you know something is running on the thread but regarding Kirby's you don't need to know anything right now we will explain everything in this session but thank you for the question cool so basically whenever I want to learn about a specific topic. And in this case, this is going to be crudites I go to a developer the dondre and I search for the topic, so in this case is going to be A Let's say groupings for example. So here basically the top search is going to be cutting corners and andred which is actually our documentation. And as you can see we have a pretty detailed guide so we have, for example like features how to execute things in the background fit and perform this we have also a visual guide for this or we have different pages. If you see here on the right side of the screen with a few things that are going to be quite useful. So for example, we have the best practice is we have additional resources we have things like flows as well that we might not get into in the session but they are definitely good resources to check out on your free time so basically we're going to be talking about groupings and actually groupings and you take a look here is our recommended solution for asynchronous programming or mandry that's why because in the past I think asynchronous programming it's quite a complex topic to face and really simplify how we approach and solve these asynchronous tasks. And one of the features to mention for example, is that they are lightweight and for example, you can run many groupings on a single thread because they don't actually block before they suspend the execution and we will see later and we will understand better in a second it actually has lower chances of creating memory leaks because it has something called structured concurrency where all these operations block of code that you're going to run I want to execute in a specific scope and whenever it does goes away for example, you are navigating away from the screen. All those operations are going to be canceled also has a pretty good routine cancellation support this is something that other alternatives like callbacks suffer from and callbacks is quite difficult to handle cancellation properly including actually like provides an easy way to do so and my favorite here is like interation so we have a lot of things covered with kolbeinn so we have a new model we have room support for the database we have so many things. For example WorkManager as well. So we will see how everything plays along pretty well. So if you listen through the guide you will see like old explanation this is kind of a little bit of theory behind it but actually today we want to complete or actually go through the kulluk either no we have time enough to complete it all but something I want to mention for example, if you're really new to current inside there are some people we have this additional resources page where we have things like specific topics like Basics cancellation exceptions and there is these first things first blog post that actually teaches the basic concepts I'm probably like I'm going to leave it open in case, we have to come back to this later because it explains things like what I put in context which I call the scope and all that OK stop talking. Let's go to a bit. So leave open as well. So basically now we're going to go through the collapse of something we can do is try to search for the Europeans Columbia basically if I do that, I get a few results. So we're going to go through the basics, which is this result here. But we have multiple things collapse apart from the basics that we are going to go through today we have the advanced things collapse which is this one here. And also from the training courses we have another one which is building a Kotlin extensions library comes up and this one is basically whenever you have nonpolluting code, how to create a bridge to convert it to crupi and having like a more idiomatic version of that specific API so you're whispering APIs like to spend suspendCancellableCoroutine grouping or call backflow that we obviously don't have the time to cover today. But Yeah let's open the club I found this to be as well open. So if you want to go along with me, feel free to do so. And so here basically good that is just a self-paced guide for you to actually code and run an application that is going to teach you about a specific topic. So this one is about confidence in your Android app. And basically collapse follow the same structure and the first one is going to be like before you begin or kind of like an introduction section and here we are just trying to set expectations like OK this is your first introduction to a specific is like what I'm going to learn I'm in the right place or not. So here am I going to say, OK, we're going to go through this going to learn about that some prerequisites. For example like you're familiar with the model repository layer and all that room database you are familiar or have some experience with Gotlieb and basically the things that you will do too much we have this question where someone was wondering what exactly is cowritten so what kind of use cases are proteins useful and should they be thinking about Currey teams as a replacement for arc's Java or Kotlin what is the official guidance here Yeah so this is our recommended solution for asynchronous programming and when we talk about asynchronous programming it's basically kind of the opposite of synchronous programming synchronous wherever you want to run something synchronises like basically I want this to be run right now I don't want to wait for this asynchronously it means that I want to run something that probably doesn't need to go to the unrated UI threat of course, because there are some operations that need to happen in the background. So that we don't block the UI because we want to have a responsive application. So with synchronous programming it's like OK we might want to run something on a different thread but also I want to execute something on this same thread but I don't want it to happen right now or better said I don't mind if it's executed like 15 seconds later because something else is being executed there's basically a way to run a piece of code as we will see that could even happen like in any threat but doesn't need to happen right now. And it doesn't need to block this right I hope that's clear and regarding the next level a solution flow for a synchronous programming and it was pretty popular in the past whenever things weren't there but a Google or an Android we recommend using croutons for this specific use case because as it was saying like all our Jetpack libraries are really well integrated with grouping's cool Thanks for the question. OK so getting set up this is another section in our clubs that pretty much all our clubs do the same and I'm here basically tells you how to download the code and how the code is structured so for example, the curtains codelab we will see later in the Studio it has a project that you download and in the project there are two little modules with we start echoed another one with the finished school just to make sure that you want to make sure that you follow the code properly or if you at the start you can see the solution there but this set up totally depends on the author and also the project that we are in charge and we are trying to solve some of these specific use case this set up works pretty well. And that's what we have been using now OK, let's move on to another Studio so basically here we are going to see an application. This is called that whenever you tap on the screen a message is going to be displayed. So I have here in the Studio that I can run the up side as I was saying here on the Studio we have the start package that the module with all our code in case, we wanted to check out the solution I would go here through the finished code module and I also have my emulator open so here I can see the application whenever I tap on the screen it's going to load you are going to see the loading spinner there and then I'm just going to count how many times you've been tapping on the screen. So here says to tabs and then kind of the title or the message on the screen is going to change. So basically what we are going to do we're going to see later in the code that asynchronously we are going to make a request to update the number of times to that we've been tapping on the screen that's going to be communicated to the UI but also something else is going to be allowed in the background. And if we take a look here that comes up it explains how the app is architecture and this is kind of follows kind of the classical pattern where we are going to have the while with the main activity and the main bimodal the main model is going to be in charge of all the UI logic that goes into main activities. For example processing the touch events the logic behind what happened here we don't have a business layer that we don't have any like in use case type of classes but we do have the Italian the it's going to be the title repository in this case, because that all the messages that you've seen on the screen they come from the network and the database. So we have to leave the sources. So we have the local paper source with the database here and the network as the kind of remote source is there a reason we're using coroutines in this specific context like what would happen if we try to do this without it is actually that's a very good question because if we take a look at the code that we go here we take a look at the code the starting code starts without curtains so if we take a look for example, maybe a model we will see that whenever we want a database it's doing something without things and now we can explain a little bit what it does but kind of the exercise of this code that is converting all the asynchronous code that we have here in the project to use coroutines and actually it's now that you mentioned that if what we are doing here updating tops what's going to do is that it's going to increment a counter and it's going to kind of simulate that something is happening in the background. So background here if we take a look it's actually a threat pull of two threads and so like the way to execute something in the background that you can use executor's and that's basically this is a way that you can create a threat to threats and basically here what we are calling it a clean submit and we're putting out runnable a block of code that is going to say, OK run this in the background. So what are you going to do it's going to slip it's going to block the threat for one second. And then it's going to update these stops which are life data are mutable life data it's going to a database to be whatever and that's going to be displayed on the screen. So that's actually something that we are going to go in a second and we're going to convert these to you to clothings and of course this code is not using grouping's and this is going to be like for using you you need to implement add some dependencies to your project actually feels like there is like also if you're currently using our server there is a here like a library the cutting room things are that basically it's an interaction between computers and you can have a bridge between those two and you're going to have to migrate everything at once OK, let's move on a little bit of theory created by my Sean I also like a pretty good feeling is very interested and one of the problems that krotons tried to solve it's reducing the needs of callbacks and here we are talking about the callback pardon but I want to show this in code and basically this is going to simplify all that let me show you some code for that. So here is a title, which is actually what's called whenever you tap on the screen let me show that. So whenever you tap on the screen says amam you click it's going to update the taps whose code we've just seen this one here and it's going to refresh the title and refresh the title it's going to kind of show the spinner and it's going to call the repo layer and it's going to call this method called refresh title with callbacks and it's passing a callback why is it passing a callback because the ripponlea is going to make an encore request, which is going to check the database in the background Fred it is not going to execute that code in the end if we were to execute the network calling that in the way Fred the spinner won't spin that's because the thread is blocked and the UI is not responsive that's why we need to move the execution to a different thread. So once that's clear basically if we execute this so reverse title gets executed spiner is going to be true we just make a call to the repo and nothing else happens. So here these functions is going to return because basically with the callback what we are telling the repo say, OK reverse the title and whenever you are done please call me back with a callback call me back can get it like that. And basically there are two ways the things can go uncompleted means like Yeah the title was referenced properly basically spiner to force because the title is going to be referenced in some other way. And if it there was an error that was not put on the screen. So a couple of problems with that as a problem with callbacks is that you need indentation it's quite difficult to read what's going on because you have a callback and then you have to implement different methods depending on the path that the request took but then like some of the problems with callbacks are OK what if I want to make another asynchronous request after this is a request I need another callback inside the callback and then it is more difficult to read and I'm one of the problems as well with callbacks if you take a look at the implementation of refresh title it's actually it's going to make that request and if it's successful it's going to update the database is that this is happening in the background right so this is Colleen as we were saying before bigram that submit and it's going to do something but this callback whenever we call here whenever everything goes well or there is an error at the callback is going to be executed on the background right but here we go back to the numeral code we don't have any clue that this code is being executed on the background and that's for readability and for maintainability of the project that's something really bad. And that's why here in the live data we have to post value instead of said the value of the value allows you to update the live data from a different thread that is not the main thread. So there is no guarantee that this code here is going to be executed on the main thread and with Corinthian's we can guarantee that OK I think that's fine this is for example anaglyph request it's going to be synchronizer it's going to be hearing the comment make an actual request is going to block the call any current advice when I start writing some great things Yeah I guess one question I had is what exactly does it mean when it says that request is going to block code what exactly is that blocking Yeah it's going to block the thread. So for example, whenever you make an request it might take some time to reach the server get that response back the but of course it's going to take some time to process the request and you need to parse the response in some way I know that all the time where the next request reaches the outer network at the internet that time that your thread is going to be doing nothing it's going to be blocked because it's waiting for the next request to come back and if that's blocked means that no other code can be executed in that threat but we've got to do is we have something that instead of blocking it is going to suspend execution and so whenever you do hit you we are talking about suspend that whenever you suspend the execution is going to suspend but the thread is going to be free to execute other things that may happen in thread. And GUID when the request comes back then it resumes execution it saves all the variables it saves everything that it needs to do to resume execution after that request comes back got it for this kind of case, what if I wanted to use an async task is that something that's valid should we still be using async tasks no easy task it was a good solution very long time ago but it was deprecated in 111 and the problem is in part because it was really easy to leak in memory and actually it was kind of attached to the lifecycle of the BU layer. And here we could be we can say, OK, we're going to see that we have we can use different scopes to tie certain requests to a different lifecycle in this case, for example, the new model got it. Nice OK Yeah I'm excited to see the lifecycle stuff OK let's try it I mean I think it's 20 minutes, I haven't seen I haven't shown any current code this is going pretty well OK OK OK I understand, including scope I think I'm going to skip this and I'm going to probably talk through it later. But basically we are sharing the model of database with some we said before that this is doing something about the threat let's convert this call this specific code which is very simple to kirkenes OK here we have kind of the solution but let me do that Meanwhile I'm going to be talking through what I do. OK maybe model. So we have this update database that we want to replace and basically whenever you want to execute something including actually is a private firm I'm going to comment this out but you and I are going to agree that the private firm it's OK and now we're going to say, OK, I want to execute this in a actually if we say like that count was not accurate. So we could certainly do that. And I have the technical and how can I do. How can I create a current team from the demodulator we have something that is called coroutines code and the new model comes with a built in audience called code which is called beamlines code. And let me touch on that later a little bit better with me for a second exactly the background to me thinking I can create kind of the same thing actually this code here the model of the launch is creating a new coroutine and I got a team you can think of it as some easy way like for example whenever here we have a background that submits that we're passing a runnable kind of can think of this as in the same way you can think of accreting as a runnable with super powers with super powers because we will see that it is really easy to do things with the background execution as well. So here we actually can do exactly the same thing and we're going to see the differences in a second OK so we have a friendship and then say, hey don't do this because this is going to look different. So I'm probably like I can do the same so we are starting with exactly the same goal and we are going to improve it OK so what it's bunol scope so I was saying like every character needs to live in a specific scope and the great thing is the scope is the if we take a look at this it doesn't matter to scope it's going to be the entry point is the way you can create a grouping and basically that with accreting the scope you can get track of all the things that have been created with this specific scope. So here we are not in accreting here we created accreting one of the things here to take into account is that the amount of the scope is configured with a willingness to purchase domain and this is the main I'm going to put that here it's better the main it's going to execute something on the main thread. So basically launch I say, OK, I want to execute this coding on this particular domain but this is not what we were doing here right here we were executing on a different thread. So the way to create a grouping that executes a different thread. So we have different sponsors these mainly tell the group where to run and we have one which is default is a threat that is already configured in this and it has a number of threats that you can use to run things in the background. So basically here we just created a grouping that is going to be executed on a background threat so obviously if we do this if we use if we execute this block of code mean. And if we as the threat that's going to be pretty bad because it's going to look at the main thread here it's kind of OK but it's not OK because obviously you shouldn't be looking at any threat because otherwise the threat becomes useless it's going to become there is going to be used however there is a way to slip in this. And that's with the delay function and delay if we take a look at it that's just brain function that is going to kind of delay the execution of this block of code for a second. And then it's going to execute this bit so what does it mean that it has to brain function here and actually you can see the right call that means that this is a suspend function as suspend function means that the execution of this grouping income to suspend and this is what it does so whenever you execute this been on the background threat it is going to wait for one second. But it is not going to look at the threat threat though this was blocking the threat but delay it's going to suspend execution what that means is that while we are waiting for one second order code can be executed on this Tread. And whenever that second passes then this code will be executed this is not known when to resume and suspend execution of a certain block of code but something we can do as well because here we can say, OK, I want to execute this imane this cold here it is not going to pass it is not going to block the main driving I think it is going to suspend execution so actually this is safe to call from the main thread because this is going to spread is going to block and so here and instead of saying possible we can actually call value and assign perhaps absolute value, we can assign you directly because it's guaranteed that this code is going to be executed upon the main thread because we executed it here something to keep in mind is that view model Scoop by default is going to use this pattern logmein so this is a little bit redundant if we call this block of gold is going to be executed on the matrix OK we created our first cherubini any questions Karen Yeah I think you already touched upon this a bit. But some of the live chat was wondering how do they know the behavior of the default dispatcher in that launch function and I think you said it was Yeah Yeah the default is better it's pretty confident in encouraging so we have like I said here you can see, there are four dispatchers available. So it is default but it's basically for things that need to happen in the background threat, then we have allele, which is specifically used for intensive operations like for example network or lisk and we have an unconfined which is something that as a beginner you shouldn't worry about it is not commonly used and not in production code that much so default for CPU intensive tasks mean for things that need to be executed on the main thread or of things that are not blocking and then allow for the rest and actually like I mean you can go into the implementation produces like a default escolar but in this case is using like 64 threats and things like that. So you don't have to worry about don't have to worry about that. That's like pretty configured for you and ready to go to be used nice I think there was another question about what would be the right way to call a suspend function on the main bread OK if you want to call us suspend function from the main thread that you create a thing with remodelers code for example, you must go to the launch. And that will be executed and that's basically how you create a curtain on the main thread from the bimodal scope we will see later that also the regulator has a different scope and so I was saying like the recruiting scope here is quite important because imagine that you are doing like a really long operation imagine something that is very expensive and it's taking a lot of time and it's going to take 10 minutes or whatever it is obviously this of memory because if you are doing something crazy and then here you are referencing something else until all of this doesn't finish this runnable or this is going to be memory the good thing about the predefined scope's is that whenever the remote is going this way, that whenever the value model goes away gets destroyed and I'm clear this new model is going to get destroyed meaning that all the characters that is execute them they are going to cancel I'll just leave you mother was like you can create your own copy if you want like for example, we can call mysql if she goes through a cooking school and basically the curriculum is going to take the group in context as you can see here and the context is basically like a set of elements that is going to configure the decorating and for example, one way to configure it is say, OK, what is the default dispatchers so numerous in this case is using these package with may also have something like a job. And if we have time, we will explain later I got the job is basically this is mainly this is it's configured with a supervisor job and this matters to me so every time that you create using mysql or demands it will be executed by default on the Main Street and then of course then view model you have to be clear that you want you can know when the view model is going to be destroyed and basically what new models go between under the hood and we can do with my scope in fact, you can call my corporate council to actually cancel all the things that are executing at this time and for example this one that is taking the minutes it's going to be x is going to be canceled because we will remove we cancel its scope. So this is a good way to not leak memory and make sure that you wrap up and clean up everything whenever the new model in this case goes away. So why do you think so by using the default scope. We don't have to specifically call cancer ourselves when the moment is cleared that's right bunol scope is doing that under the hood and that's why it's an easy way to get started with curtains otherwise you would have to create your own scope and clear it in all your models if you use bimala scope that boilerplate goes away because everything is done for you cool Thanks for clarifying that OK so actually something worth mentioning is that there are some questions and some confusion regarding when do you create a school in which letter basically I recommend creating a grading school whenever you want to control the lifecycle of groupings and basically I would create a Gradescope for the new model later because I that's kind of attached to the BU lifecycle and he knows when the screen is going to go to the background moscoso base configuration changes. So in under it you know like the new model school it's a natural place to start creating things but then if we go, for example, to the ripple layer a ripple layer if it's doing an operation that is linked to the screen as we are going to do right now it doesn't need to create a critical school it just exposes brain functions and we will see in a second actually let's move into that and undo that I think I mean not following the collapse that much to be honest. But we are roughly here in section where we created a accreting here I think we're going to talk now about section number and we are going to basically convert this refresh title into intercutting so basically what we are doing basically it's I'm going to copy this code a refreshed title I'm going to go ahead and copy that into my understanding here and maybe model so basically as we were saying glutens read sequentially we were saying before that routines are going to remove the need for callbacks and that's because in the callback you're saying, OK whenever you are ready whenever you finish your work then execute the callback that I'm passing to you and that's because the mechanism work in that way. But we do things instead of calling a callback we can suspend our execution until that work finishes and that's what we are going to do right now so refresh title ridgeley let me come in this old refresh title here the previous implementation is using callbacks but with thirteen's actually executing this on the main thread we are calling we are showing the spiner we are calling the report and then in case there is an error I want to show the snack bar. And finally whenever the Refresh title function returns then we put this in a default because we have finished loading the items that you can see with croutons we here we will see later that refreshed title it's going to be a suspend function. So whenever you call repo refresh cycle this block of code is going to suspend execution until refreshed title finishes so there is no need for callbacks because the next line of code here next line will be called where will repo finishes refreshing the title that's pretty neat and that's why you can see all the complexity that we have here with callbacks the complexity goes away like you can read this function you can read this kind of thing and it reads sequential like everything has a sense. One thing gets executed after the other OK I refreshed title how basically it's complaining because we don't have a refresh title but let's create it now so I'm going to create that suspense function refreshed title and this one is not breaking any parameters yet. So you can see I created the suspense function. And now the clutter icon appeared it means that this kind of thing can suspend execution OK so suspend function that this was the key word here basically we are telling the Kotlin compiler that this code needs to be executed and that's just by simply having the keyword there is function cannot be executed from a regular function. For example, if we come here we are hearing refreshed title from the New model here I'm not in a courtroom and I cannot call regretable because he's going to give me an error and say, hey such brain function that needs to be called from within occluding and that's basically how we want to guarantee that these group and specific functions run on occluding OK so let's go back here we're pretty much going to do the same exercise that we've been doing before we have the code here we are going to convert it to accurately so basically I'm not going to submit these runnable or this work or this block of code into the background threat I'm going to execute that code inaccurately so basically of course now what happens with the callback well, we don't need a callback because basically this is going to return whenever it finishes so because this is the kind of a bizarre little bit harder to read because we have pretty much assuming but basically instead of calling uncompleted we don't do anything the function is going to return the suspend function is going to return because there is nothing else to do. And instead of calling the callback with an error something we can do it instead throw an exception and we can say, OK, I want to throw here the type of refresh error if I could then be able to replace the title I'm pretty much the same here so that happens through the exception. So you can see it's actually reads pretty well. So I'm going to try to do something here. I'm going to make this request that this synchronize and we will see a leader how to avoid this. And if it's successful I'm going to insert the title in the database. And if not I'm going to throw an exception that the grouping is going to catch we will see later that actually this first title has a three page show here it will come to this OK if I don't do anything if I don't got anything here this has been the function is going to be executed on the same thread where the Corinthians has been launched and in this case because this was launched in these pages the main discussion is going to go to the main UI thread 100 and this is going to block the thread because this is a or something we can do to move the execution to a different thread is using a function including what is called with context and with context basically what we are doing is saying, OK, this piece of code that I'm going to tell you execute it in a different context. So something we can do is that this matters because we are doing have request I can certainly have that in your dispatcher so execute this block of code that I'm putting you in the other thread and now and this is safe to be called from the main thread. So this is called from the front whenever it comes here I'm going to swap the execution of this thing to be done in the area. So now all of this is going to be in the abstract if we take a look at with context what it does is that these are suspend function, meaning that is going to suspend execution and actually it is going to the grouping that caused this function it is going to wait for this block of code to finish before returning so something like we can do instead like here I want it to be clearer, and it doesn't read very well but something I can do it's doing that reverse title and basically I can call with context inside this thing. So here are these executes on the calling this pattern actually this will be this part of the group in this part of the block of code will execute on the main thread and now I'm swapping to the thread. And all of this is going to be executed on I use it on a tripod that is configured for that obviously still this is a blocking code it will block the other threat but it won't block them minimize and that is what we care about 200 cool any question Carol Yeah I think Maya had a question about what's the difference between blocking and suspension because a lot of times you're saying something has been blocked and then you're like hey we're going to create a suspend function. So you kind of give us more tomorrow that Trump so here as I was saying with context is going to suspend execution and I was saying like after OK this is a pretty long line of code let me see if I can do this OK so with context here this is going to suspend execution until all of that in here finishes meaning that now we scumbag's only back here like this is going to execute on the goal in this particular well as well right so what it means with suspense is that you're executing on the main thread the is executed on the main thread now I come here and it's going to suspend execution until all of that finishes what that means is that whenever it comes here it is going to be on the main thread as well. But the current execution suspended while all this was happening under your thread. And because it suspended it means that now the only threat the main thread was the killing dispatcher is free to do other work so Meanwhile they are your request is happening the way Fred kind of still being the spinner that we have. And so basically suspending means that hey I'm going to park this block of code that I'm executing and going to put it in a specific bucket full for later and I'm going to be executing other things that are being dispatched to my thread. And whenever the actual finishes whenever like this piece of code here finishes, then I'm going to take that routine back and I'm going to continue the execution if we see like the blocking call if this was a blocking call that wouldn't happen. So if this is blocking the UI the threat wouldn't be able to do anything else it will be blocked the spinner won't be able to spin because the thread is busy waiting for the other request to come back versus with good business bad behavior it's free to do whatever they want it wants to do and then it will go back to that execution that that was left in the middle and then carry on executing and what it's called it is going to resume executing so resume executing on the main thread got it that makes a lot more sense than shib had a follow up question is a guarantee that the same thread will resume the execution after he got expelled suspended or are we not sure about that right so the main thread is dispatcher's logmein is configured with one threat so here because we were saying that default has 64 threats if we do this pattern that I you're here and and then we deal with this context again with these pictures and you obviously this is executed executed on mean it is not guaranteed that they could get executed this
Info
Channel: Android Developers
Views: 44,211
Rating: 4.9310346 out of 5
Keywords: GDS: Yes, Android, android code-along, Kotlin, Coroutines, featured, kotlin coroutines, android code along, android code, android developers code along, android developers code-along, android live, android livestream, developer, developers, android developers, google developers, android, google, Manuel Vicente Vivo, Caren Chang, yt:cc=on, cc_lang_pref=en
Id: FWxeDqM_WIU
Channel Id: undefined
Length: 58min 47sec (3527 seconds)
Published: Wed Mar 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.