Kotlin Coroutines with Android project | Catalin Stefan | Skillshare

Kotlin Coroutines with Android project

Catalin Stefan

Kotlin Coroutines with Android project

Catalin Stefan

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
17 Lessons (1h 31m)
    • 1. Class intro

      2:21
    • 2. Install required software

      2:38
    • 3. Coroutines

      7:01
    • 4. Hello world

      6:35
    • 5. Coroutines are lightweight

      2:56
    • 6. Scope

      6:37
    • 7. Context

      4:54
    • 8. Suspending functions

      5:57
    • 9. Jobs

      7:55
    • 10. Dispatchers

      10:03
    • 11. Async

      6:20
    • 12. withContext

      3:12
    • 13. Exception handling

      8:48
    • 14. Project intro

      2:09
    • 15. Download an image

      8:27
    • 16. Challenge

      0:40
    • 17. Apply the filter

      4:24
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

37

Students

--

Projects

About This Class

Kotlin Coroutines

This class is all about coroutines. It will show you how to build your first coroutines to run your processing on a background thread. Then we will go into all the coroutines basic topics like

  • Scope

  • Context

  • Suspending functions

  • Jobs

  • Dispatchers

  • async

  • withContext

  • Exception handling

Finally we will implement coroutines in an example Android project.

Meet Your Teacher

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Class intro: Hello, everyone and welcome to this class on Scotland co routines with application on Android. So what are we going to talk about? First of all, we will introduce the concept of co routines, and we will build a hello world application that will show us how to implement a very basic core ity. After that, we will go through a few videos where we introduce various concepts that relate to co routines. Because, of course, it's not useful to only know how to build a basic co routine. But we also need to understand the various components that go into building co routines so that we have the flexibility that we need. So we will discuss things like scope suspending functions, jobs, dispatchers, handlers and so on and so forth. Then we will talk about exception handling, which is a very important topic that is sometimes for gardening classes, on co routines and in Cortland in general. So we will talk about how we implement exception handling in our code and in our programs. The code that we will be building up to this point will be in coddling the reason why I don't want to learn about co routines directly on Android is that android is a whole ecosystem that not only requires a lot more knowledge, but it also introduces dependencies in our code. So in order to separate the co routines functionality from android and study it more easily , I've chosen to build core proteins in cotton directly. Finally, we will be moving to Android, where we will be implementing a class project. In this project, we will be building an android app that is designed to show you how you can implement a piece of functionality using code routines. So we will be downloading an image. We will display it in the application. Then we start up a co routine and process it in a certain way. Once the processing is complete, we will display the final resulting image. Now we will see that the processing cannot be done on the main threat. Otherwise the application might stop and it might crash. So we need to put it on a background thread and we will do that with co routines. All right, so that's the class. I will teach you all you need to know about co routines as well as how to implement them in an android application. I'm looking forward to getting started. I will see you there 2. Install required software: Alright, guys. So let's go ahead and install the software that we're gonna need for our class. So first of all, the first part of our class will be focused on building co routines directly on Scotland and in small Cortland programs. Right. So we won't be using Andrew Studio for the first part of our code. We will be using another editor now, of course, you could use pretty much any Scotland editor you like and you can even use something like a note pad if you really wanted to. But I do recommend you start off with a nicer editor. That gives you a lot more functionality. So the one that I prefer and the one that I recommend to my students is the intelligent I D . A. If you've never used this particular one before, it's got basically the same foundation as Android Studio. Andrew Studio is built on top of intelligent I d. A. So if you've used under studio before, you will be very familiar with intelligent Okay? And apart from that, you can use it not only for Scotland, but you can use it for any software development language. As long as there is a plug in, you will be able to build in that language. So it's a very versatile editor. OK, so if you want to install that one, you need to either search on Google for intelligent idea or simply go to jetbrains dot com slash i d a. And click on download. Now here. Very importantly, you have two options for the download that make sure you use the community edition right. This one is free. It's open source. There are no issues. If you choose ultimate, it might have some features for enterprise development. But my guess is you're not interested in those features at the moment. So go ahead and download and install the community version. The installation is very, very simple, very straightforward. So you should have no problems, whether you're on Windows or a Mac. Now, the second piece of software that we're gonna need is obviously android studio. My guess is, if you're interested in this class, you already have that installed and set up. If not, just go ahead on the Android Studio website are at Developer that andre dot com four slice studio and download Andro studio. From here. It might take a bit more time to install. It is a large piece of software, and it needs a lot of components, but you should go through it without any problems. All right, so that's all we will need. The first part of the course, the more theoretical part will be done in Tell A J, and then we'll move on to Android for the practical application. 3. Coroutines: all right, So in this video, let's briefly discuss what co routine to bring to the table and why we might want to use them instead of threads. So the main problem with threats are is that threats are resource intensive. Okay, so it takes a lot of resource to start a thread, stop a thread, coordinate between threads and so on. Meanwhile, co routines are lightweight threats and in fact, are very, very, very lightweight threats. So we have a program where we start about a 1,000,000 co routines, and there is no problem on the memory, right? If you try to start even, maybe 1000 threads, um, your program will run out of memory, will crash, but co routines are very, very lightweight, so you can start as many as you like with no overhead with no problem. OK, so basically co routine to use thread pools. A threat pool is. Let's think about it as a bunch of threads that you can use whenever you like, right, so you have a small co routine, which is a small unit of execution. Then you assign it to a threat. When that coating finishes, the threat is put back in the threat pool, ready to be reused by another co routine that need it. Okay, so they re use threats. They use very lightweight functionality so you can start as many as you like, with absolutely no impact on performance. Now they simplify greatly a sink code. Okay, So called maxing synchronization are very, very easy to use in court routines. And actually, they make parallel programming look very much like sequential programming. So you can have you can start a co routine in your code and immediately access variables and methods in your program without any overhead. And that is how easy it is to do callbacks from a co routine to your program. And synchronization is also very useful. You have just two or three methods that you can use to synchronize between co routines without any overhead, whereas threads are very complicated. And if you've ever worked with threads, you know what a headache they can be, especially when you start a lot of them and need to synchronize between them on. And they have a very, very simple congress intact. So they have a few concepts that we will discuss shortly that fit together very nicely. And once you understand those concepts, they are very easy to use to start co routines and execute code in parallel. Now they can pause and resume at any time, and a cool routine is not bound to a thread. A thread is simply a place to execute the called routine, but the called routine itself can be stopped at any time and restarted at any time. So in that way they are very lightweight and can be reused as many times as you like. Now let's go through a few basic concepts of co routines, and here I'm just gonna list them. And then in the next few videos, we're going to go through them one by one and practice them in our application to see how we can actually use them and how they perform. So the first idea is of a scope. OK, this cope is what creates and runs co routine. It provides life cycle events, so things like pausing a co routine stopping canceling a core team is handled by the scope . Now the context is a concept that is very tied to the scope, so the scope itself provides a context and a context is simply thes state off a co routine . OK, so it provides some variable, some functionality that you can use in your co routines. So that is the context. The scope and context are very tightly tied together Now, suspending functions are basically functions that can be run in a co routine or can be suspended as we call them. So basically, they provide the functionality that you use to run in peril that you want to run in parallel. Next up, we have jobs. Now a job is basically a handle on a co routine, and you can use a job to access lifecycle methods of a co routine. OK, so when you create a co routine in a certain way, which we will see when we get to that lecture, you will create a job, and a job can be used to, let's say, cancel the co routine if you so choose later on. Next up we have a deferred, which is basically a core team that returns a result, but since Corentin runs in parallel, you cannot return the result immediately. The result can only be returned when a co routine finishes its execution, so That means we need a deferred, which is basically a future result of a co routine. And what you can do with a different is basically tell the program to wait for the outcome of that co routine when you are at a point where you need that result. Okay, so that is the deferred. Next up we have a dispatcher which simply says that a dispatcher, you know, starts co routines on thread. So it manages a certain number of threads, and whenever a co routine needs to run, it will assign it to a threat and run it on that particular threat. So dispatchers, we have just a few of them that are more or less suited for certain tasks. And we will talk about dispatchers and what what this patters are suited for which tasks we will talk about that when we reach that video. And finally, we have ever handling. Now air handling is kind of self explanatory. It basically provides a way to handle any errors that might come up in a co routine. OK, so we have different ways of handling the errors based on how we might start a cover routine, and we have a whole video to talk about error handling for our co routines. So that's it. These are the major concept of co routines. Of course, there are some some details about each of these that we need to talk about. But these are, as you can see, there's not too many of them. I've listed here about seven. There's probably one or two more that we will discuss later on that are very related to one of these basic concepts. So there's not too many. They kind of fit together really nicely, like a puzzle so that you can, once you understand the basic idea of co routines, you can easily, you know, play around with all these concepts to give you the functionality that you require. All right, So without further ado, let's go ahead and start to create our first co routine, and then we'll talk about what that means and how we achieve what we are trying to do. 4. Hello world: Alright, guys. So in this video, we're going to start to build our first co routine. So open up your intelligent idea and let's go ahead and create a new project. Now, the way we're going to create a new project is we're not gonna create a couple in project will not create a greater project. The reason for that is that CO routines aren't part of the basic default Coplin functionality. They are a separate library. So we would need grade all in order to be able to add that dependency to our project. So we're gonna sell it great all here. And we got decent of Java and instead select Scotland slash J D. M. Okay, so we want the coupling that runs on the Java virtual machine. Now I'm gonna use 1.8 I. There might be some issues with other general versions, so make sure you use 1.8 as well. Let's go ahead and click next. Now, give your project and name whatever you like your project to be called. I'm just gonna call this co routines basics. Okay, Chris, base that now you can give whatever your main you like here it doesn't really matter. Um, now, if you open up this artifact coordinates, you can edit these values as well. So you can put a package name here if you like a non artifact, I d version. Whatever you like. For me, the default works just fine. So I suggest if you're just learning this, just leave them as they are and just click finish. All right, so there we go. We have our project that is building in the background. Now, the first thing we need to do is we need to add the co routine dependency to our build upgrade. Also, that we are able to use it in our coat. So in order to do that, I'm going to open up the bill dot grade Oh, file And what we need to do. Very similarly to how we add dependencies on android. We need to add a the penalty to our core proteins here inside the dependencies block. Luckily, this is very easy to do. Let's go right ahead and right. Click anywhere on the file. Click on, generate, then add maven artifact dependency. Okay, so here in this search box, we're gonna search for coal routines. Okay? and then we should find the 1st 1 should be co routines core. Now, 13.1 is the latest at the time of recording of this video. So I'm gonna use this particular library. I'm gonna click add now, if any of that didn't work for you, go ahead and type out this compile code here, and that should be fine. You should have a pop up box at the bottom here That just says that Gretel needs to rebuild the project so greater will go ahead and download that library for us and added to our dependency. So I'm gonna click on enable also important so that this is done automatically for us. All right, so that is done for greater Now, what I would like to do, I'm gonna create a new file and start to build our project. So I'm gonna open source than open main right click on Scotland, New Scotland file that I'm gonna call this hello world. Okay. And here I'm gonna create the function made. All right, so inside this function, I'm going to do two things. So first, I'm gonna launch a co routine to print out the second half of my hello world string. And then in the main code, I'm gonna print out the first half off the off these drink. Okay, so let's go ahead and do that now. So first thing I'm gonna do, I'm gonna create a global scope. Okay? That should bring you a pop up by the i d. And make sure you select the content extort quarantines, global scope, which will import the correct global school for us. And I'm gonna say dot launch. Okay, So this is how we launch a very, very, very basic authority and inside the security, what I'm gonna do first, I'm going to delay the execution for 1000 milliseconds, and that means one second. And then I'm gonna print line the message world okay with an exclamation mark. So what this court routine is gonna do is gonna launch in the background, is gonna delay for one second, and then it's gonna print a message now, outside of the core routine, but still inside our main function, we're gonna print out a message, so I'm gonna print line here. Actually, I'm just gonna print not front line, and I'm gonna say hello comma space. Okay, and then what I would like to do here. I would like to do thread dot sleep for 2002 seconds. I want to sleep this threat so that I give the Corentin a chance to finish and then add the second part of our message here. So that is all we need to do. Let's go ahead and right. Click and click on run. Hello, world Katie. All right, so you can see that here we have the first, the main program that prints out a hello world. Then the core team finishes its delay and returns with a print line world that completes our message. And then the threat has finished leaving, so it will come back and complete the program. So that is basically a very, very simple cooperative. We are launching it in the background. We're continuing with our program. We are waiting for 2000 milliseconds. That is two seconds. And meanwhile, the co routine will come back and print out the rest of our message. So to make that a slightly more clear, I'm gonna put two seconds here and three seconds for the sleep off the main threat, and it's go run again. So we see our hello message than two seconds after we get the world and one second after that D program finishes. Because, you know, this thread dot street past finished is well, so very, very simple co routine just gives you an idea of how you might go about creating one. But of course, throughout the next few videos, we were building to a lot more detail about what each part of this coat means. How we can create more co routines in a more complex way, and we will see more options on how we can run them and what we can do with them. But for now, that is all for this video. 5. Coroutines are lightweight: All right. So what I would like to do in this video is I want to show you how lightweight co routines are. And we're going to do that by starting up a large number of code routines and having them print out a simple message to the council. All right, so we have our main function, so I'm going to run blocking, and here I'm going to say repeat for let's say, 100 times 100,000 times. OK, so we're gonna start up the 100,000 co routines on, and each of those will print out a message to the screen. Okay, so I'm gonna say launch. I haven't got a print line, just for instance, a dot OK, so we're gonna have 100,000 dots printed to the screen. The reason why I want to print this is because it's a very lightweight functionality for our corporate ease. The main point of this video is to show you that if a Corentin is very lightweight in functionality, um, it is also very lightweight in terms of resource is that it consumes. Okay, so we're not gonna focus on the functionality of the core routines were actually going, going to focus to see how lightweight co routines actually are in terms of resource is on the machine that they're running on. So 100,000 co routines. Let's try this out. I'm gonna run the code and there we go. I'm actually print lining it. So let's just print and I'm gonna run it again. And there we go. So we can see how easy how quick the co routines are. It was barely even a second right s. So that's 100,000 co routines that if I put a 1,000,000 co routines okay, a 1,000,000 code routines that should take about, I don't know, maybe less than 10 seconds. So let's go ahead and run the coat. And there we go. Our co routines are running, and that was about four or five seconds. If that so you can see that starting up a 1,000,000 co routines is very, very lightweight. There's barely any impact on performance of our machine right now. Try starting a 1,000,000 threads, you will crash. Your machine will crash pretty much instantly, right? So co routines are very, very lightweight. The point of all this is do not worry about the performance impact of starting a lot of co routines that they are very lightweight. There is no worry. They're the only impact that they might have is that is, if the functionality inside of the co routine, um, is very heavy, right? So in that case, you might want to think about performance. But in terms of starting many co routines, that is really, really not a concern. So go ahead and start as many as you like at any point in your code. 6. Scope: Alright guys. So let's talk about scope in relation to co routines. Now. Scope simply put, provides lifecycle methods for co routines and allow us to manage the core routines to start and stop them. Okay, now we have already seen the global scope when we ran the hello world coat, we have global scope dot launch. Okay, So global scope simply means the scope of this co routine is the scope of the entire application. OK, so this Corentin will not get finished. So if it is running in the background, it won't be stopped unless the whole application stops. Okay, So quite important. This is a very large scope and it's usually not used. We've used it in Hello, Well, because it's very simple, very easy. It allows us to create a background threat, not a background said, but I call routine in a very simple way. But it's not very not very commonly used. Let's say, next up we have run blocking now run blocking creative scope and run the core routine in a blocking way. So this'll again. You would not use it very often. You would only use it when you want to stop the execution of a code and run your code routine. One other situation where you might want to use it is if this is the only thing that your program does, and we will use this quite extensively in our examples to start a scope for our co routine when this is the only thing that we are trying to do. And finally we have co routine scope that simply creates a new scope and does not complete until all the Children of the co routine complete. Okay, so we are creating a scope. We are running a co routine, and inside that scope we can create other co routines. This call routine that we start here does not complete until all the inner core routines complete as well. So here's how you might use them. You have a run blocking that will have a launch launch is the key word to start a call routine or rather, one of the key words to start a call routine on Do you would just print out some message, Then you have global scoped out launch again. It is a way to start the co routine. You would have again some message and then, of course, the co routines cope. All right, so let's go ahead and put these concepts in a program. All right? So the first thing I'm gonna do here in Maine, I'm gonna use the run blocking, um, functionality here, and I'm gonna launch a co routine. Now here, we're gonna say DeLay of 1000 L Okay, so this simply delays the execution of this co routine by 1000 milliseconds, which is one second. And then we're gonna print line task from run, run blocking. All right. So the reason I'm print lining this task from running looking is I'm gonna run a few different co routine scopes, and I'm going to see which one starts first and how they work. Now, I'm using run blocking here because this is the only thing that we're gonna do in our main functionality. Okay, so it's okay to both the execution here. We have no other threads. No, you. Why that we need to keep open. Okay, so we're just run blocking and we're launching an authority now inside the run blocking After we launched our co routine, we're gonna use the global scope, so I'm gonna say global scope. Okay. Make sure it's like the cult. Next up call routines one dot Launch. And here we have a let's say, a delay off. That's a 500 else. 0/2 a second. And then we're gonna print line on task from global scope. All right, so we have that, and next up, we're gonna have our code routine scope. And inside here, we're gonna use the launch again, and we're gonna delay for 1500 l, which is 1.5 seconds, and then we're gonna print line, um, task from co routine scope. And just for fun. Let's go ahead and print line a message here at the top. I'm gonna say something like program execution will now block and print line at the end program. Execution will now continued. So the reason I'm printing this is because I want to show you that this is blocking so that these messages will come before this message at the end. Okay, so we're printing out this. We're running this in a blocking way. We're only finishing the blocking when all the co routines inside have finished. And once that is finished, we are printing program execution will now continue. So let's go ahead and run this main function here. Now we are getting program. Execution will now block. Okay, so that is expected. We have this message, then were run blocking here. And the 1st 1 that will finish is the one with the smallest delay, which is global scope dot launch, which has half a second delay. So we're getting task from global scope. Then this one has one second delay. So we're getting task from run blocking. And finally, the last one which is tasked from CO routine scope. We get here after these three finish, the run blocking will finish, and then we can continue our execution. So we have program. Execution will now continue. So you can see how we can play around with the different types of scopes to launch our core proteins in different ways the run looking global scope for the entire application, or create a custom scope that we can run our co routines in 7. Context: Now, the concept of a co routine context is very tightly related to the scope. OK, so scope and context are very similar. They're basically the same contact concept, but used in different ways. So a context is a set of data that relates to the core ity. It's as simple as that is a set of variables, um, that you can access inside of a co routine. Now all co routines having associated context. And that means when a scope creates a co routine, it automatically provides the context for that core OT scope and context are very similar. The only difference is that scope is used to create and manage coal routines, so that means you can create them. You can stop them when all the inner core routines have finished, all the execution has finished, whereas contact is the set of variables and data associate ID with that call routine. So there are a few elements of a context may be. The most important are the dispatcher, which simply decides which thread the co routine is run on and we will see dispatchers later on. In our course, we have a video specific for that and job which again? We have a video specific for that, but basically is a simply a handle on the co routine life cycle. Okay, so we can use a job Teoh, for instance, canceling co routine. All right, so that is the basic idea of a context. Let's go ahead and put some code in to give an example of how we might use the context. OK, so let's go ahead and create a co routine, and we will access. Let's say one piece of, um, data from that core routine context. So I'm gonna say run blocking. Okay. Then I'm gonna launch a co routine. Now, this time I'm gonna pass some data to my co routine, and I'm gonna use the, um, function call here. I'm going to say cool. Routine name. Okay. I'm gonna give it a name. My cold routine. Okay, I'm just gonna give it a name so you can pass a name here to our not and inside Arco Teen. I'm simply gonna print line some message this is run from. And here I have an expression. I have this dot co routine. Cool, routine context dot Get, I'm trying to get a key that will return me a value. And the key is cover teen name dot key. Okay, so that will give me the value off that co routine name from CO routine context. Now, we can, of course, remove this this keyword because they simply relates to call routine context. And the Coubertin scope is basically structure that contains a core routine contents. So let's go ahead and run this code. I'm going to right click run context up Katie. And then we have our co routine name, which is my co routine. Now I want to show you something else here. So inside, let's go ahead and create a global scope dot launch and I'm not gonna put anything here. The only reason I want to do that is I'm gonna command or control click. OK, so hold down command on a Mac or control on a PC and click on global scope, and that will open up the global scope class or rather, object in this case. And here we can see that global scope actually only contains one variable, which is the core routine context. OK, so this is created when the global scope is used and here we have the core it in context, which simply has some information. Okay, that is the only thing that the core routine scope contains. Otherwise, it just contains some functionality. But the only data that it has is the co routine context. And it is an object. So it is a singleton. This is the global context for our application. The only reason I wanted to show you that is basically global scope and call routine context are kind of the same thing. Global scope contains a co routine context and only one piece of information. All right, so let's go ahead and close that I'm gonna delete this launch and that is it for this video . 8. Suspending functions: Okay, so let's talk about suspending functions now. The idea of a suspending function is quite easy. It's simply a function that can be run in a co routine. OK, so if you try to access a function from a cool routine, you will get an error unless you make it a suspending function. All right, so that's simply put function that can be run in a co routine. Now the main advantage, I would say off suspending functions is that they make call backs seamless. Okay, apart from structuring your code into separate function, which, of course you need. But also they make call backs very, very seamless. So you can, um, you know, execute some code in a co routine and then when you need to access a local variable in your main program, you can do that easily within a function, and we will see that we will see how we can do that in code. Right? So we have a function say hello. That prints out a message. Hello, and we mark it as suspense so that we can use it in a co routine. And then we can simply global scope that launch launching a courting here and call the function from our core pretty. So let's go ahead and put that in code. We're going to create a small program that runs a couple of functions and updates a local variable. Okay, so we have Let's go ahead and create our suspended function here. Um, let's say complete message and we will see shortly why we call it that. First, I'm gonna delay by 500 milliseconds and then I'm gonna print line world. Okay, so obviously, this is going to be part of a hello world message, and we're gonna use the function complete to complete our message. And importantly. So I'm gonna have here a variable. Um, let's save our function. Calls equals zero. The function calls variable will simply track the number of calls to a suspend function. Okay, now here is the important part. Function calls is part of our main application. However, suspend function complete message will be part of a corporate e. And here it here is how easy it is to synchronized between our main function. Our main thread. Let's say, an acre rooty. You can go inside the core routine and simply say function calls plus plus. OK, so that is it. That is a sequential way of accessing parallel processing. Okay, so we're simply updating the variable here. There's no need for synchronization. There's no need for waiting between the the threads. There's no meat for, you know, seven fours and things on that. If you don't know what that means, don't worry about it. Co routines make those things obsolete, basically. So here we are, simply updating the variable in our main threat. All right, let's go ahead and create another function called Let's Say, Improve a message, Okay? And this one will do kind of the same thing. So we will have a delay of, let's say, 1000 l one second and that it will simply print line a message. Something like suspend functions are cool, functions are cool. All right. And then we're gonna update our function. Calls of variable here is Well, so you know what remain program. Let's go ahead and launch these two, these two code routines and then we're gonna do a bit of processing there as well. So we're gonna say global scope. Okay, let's make sure it's cotton. Next are Cortines dot launch okay. And here. We're gonna have complete message again. Global scoped up launched. So we're launching another one. We have improved message. Okay, then I'm gonna print so not print line. Just print your print Hello? With a space at the end, Then I'm gonna have my thread dot Sleep for two seconds. 2000 l and then print line that print. I'll print out the value of this variable here. Okay, so there have being dollar function calls calls so far. Okay, so at this point, we're checking how many functions we have. How many functions have called or updated this variable. Okay, so it's not a very complicated functionality. It's probably not very useful in a real world situation, but it does highlight how we can run code from a function in a co routine and also importantly, how we can update local variables from a cover t. So let's go ahead and right click. And so, like, run. Right. So we are getting hello. Half a second later, we are getting the world. Then we are getting the second message from the second function. And then we are checking the variable and we can see here that in the main thread. We are accessing the variable that has been updated by the co routines. Okay, so this is how the synchronization works. It is very easy to update functions or rather, variables in the main threat from the authority. So we have two calls so far. 9. Jobs: so a job in the context of co routines is basically a handle on that co routine on the piece of code that is running in the background. So a dot launch call will return a job. Okay, so so far, we haven't captured that outcome. But actually, you can put that in a variable and use it later on to manipulate the actual Cobra team. So, like I said, allows us to manipulate the life cycle. Now, jobs have a hierarchy. Okay, so jobs live in the hierarchy of other jobs, both as parents or Children. So this is a simple in example, you have a job here that has two Children, and one of the Children has another child, right? So you have a hierarchy of jobs Now, this is how you would basically create a job or a job within a hierarchy. So you would have here a job one that is created when we call launch on the global scope and inside that global scope, we created to routine scope and then inside that we launch our job to. So in this particular case job two lives inside Job one. Now we can access lifecycle methods in using the job, the job variable. So things like cancel that allows us to cancel a job or join, which basically joins the job. The color team to the current threat. Okay, to the main thread, usually now importantly, if we cancel a job, all its parents and Children will be cancelled. Two. Okay, So these jobs within a hierarchy depend on each other, and if one is cancelled, then through the others will be canceled as well. Now, the best way Teoh get used to jobs is to practice them in code. Okay, so let's go ahead and create a few jobs in our main program. So first of all, I'm gonna do here a run blocking, okay, to create a co routine context or call routine scope. And inside here, I'm gonna have a job. Okay, so I'm gonna say Valle job one equals launch. Okay. And here, I'm just gonna do something. Okay. I'm just gonna print line. Let's say job one launched. Okay, so this is the job one. All right. So after I have created and launched job one what I would like to do here, I would like to say job one dot invoke on completion. So this is a life cycle method hook that we can use to process some code to do some code when the job is completed. Okay. Whether it is cancelled or just finished by itself and hear what I would like to do. I'm gonna simply print line. Job one is completed. Okay. Job one completed. All right, so that is it. Let's go ahead and run the code as it is now. All right, so that's simply creates a job. Okay, We have Job one launched, and we use that handle that job object to attach some functionality to its on completion. Now, what I would like to do, I would like to cancel this job while it is still running, and then see what the outcome will be. OK, so first of all, I need to put a delay here inside the job. Otherwise the job will run immediately. Okay, So I'm gonna save delay of 303,000 L. Okay, so that's three seconds. I still have the invoke on completion, but I'm gonna say job one dot um cancel. Okay. So I'm just gonna council the job, and here before that, I'm just gonna print line Job one will be cancelled. Okay, Let me just add a delay here of 500 l just half a second when we created the job. We have a delay we invoke on completion. Actually, this can come before this doesn't really matter. In fact, we have the delay. Then we print line job one will be cancelled, and then we actually proceed to cancel that job. So let's see what happens now. Okay, let's go ahead and run now. Importantly, Job one launched is not run anymore because we are having a delay here. So what we will do? We are delaying half a second, and then we are saying jump one would be cancelled and then we actually canceling it. So this statement will never be run. Instead, this will be run. Since we are cancelling the job, this will be run whether the job finishes by itself or is cancelled. Ok, so we are getting job one completed. Now, what I would like to show you is how we can create a hierarchy inside off job one. Okay. And then what happens when we actually cancel that job? One. What happens to the hierarchy. Okay, so inside of jump one, we have Job one launched. I'm gonna comment out this delay here. So here, I'm gonna say valve jump to is going to be launch. And here we have a delay again. Three seconds, and then we're gonna prank line. Job two launched. And actually, we can print like this before the delayed, okay? So that we're going to get this message as soon as the job is started, and then we're gonna delay and what I'd like to do here. I'm gonna print line job, too, is finishing. Okay, so that is job to I'm gonna say, job to dot Invoke on completion print line. Job to complete it. Okay, so we have that. And let's add another one. Another job inside here just to have multiple Children. Okay, somewhere save al Jobs. Three is launch friend line. Job three launched. We're gonna have a delay of three seconds and we're gonna print line. Job three is finishing. Okay. And their jobs, three dot invoke on completion print line. Job three completed. That is just to kind of show us what happens with multiple Children. Okay, so jump to and job three are now Children of job one and what I'm doing here. I am canceling job one. Okay, so let's see what the print out is going to be. All right, so we have job one launched job to launch. Jumped three launched. Now importantly, we're never getting this job too. Is finishing in Job three is finishing. Why? Because we are getting job. One will be cancelled. OK? And then we are proceeding to actually cancel that job, and we can see that we are cancelling Job one. Therefore, we are cancelling job to end job three. Okay, so we are getting job to complete a job three completed, and then job one completed. So the whole hierarchy will be cancelled if one of the jobs will be cancelled. OK, so that is how you play around with with jobs. You can use the job object to invoke lifecycle methods on that particular co routine. 10. Dispatchers: All right, So let's talk about dispatchers now. A dispatcher basically determines which thread or thread pool the co routine runs on. So you don't necessarily need to define a dispatcher if you don't want to. You can run co routines very easily, like we've done so far without specific specifying which dispatcher we want. However, if you want to be a bit more precise on how your co routine runs, you can specify a dispatcher. Okay, so different dispatchers are available depending on the task you want. Okay, so some dispatcher's arm or suitable for network communications, others are for processing. You know, a large amount of data. Others are for you. I communications and so on. So basically, you decide which dispatcher your co routine will run based on what the core routine actually does. So how we use dispatchers, Basically, we have the launch function and we can pass a parameter to launch function like so dispatchers don't default. Okay, so default will basically run very CPU intensive processing. Okay, that is what the default dispatchers for. So we have a few common dispatchers that we can use, and I have listed them here so that we can see which dispatcher is for which kind of task. So the main one, the dispatcher dot main, is for updating you. I driven applications So for example, android is very you. I focused So we will use the meine dispatcher when we want to update the u Y. If you've developed on Android before, you will know that the u I cannot be updated unless you are on the U A threat on the main threat. So you need to use the meine dispatcher if you want your co routine to update your you I in Andhra very, very important point. Now the main dispatcher needs to be defining grade all and this is done automatically for us in android applications. However, in our Coplin example that we run on the on the intelligent idea We do not have this made dispatcher at our disposal. We will try to run it in code and we will see the error that we get so we cannot use it here unless we define it ourselves. All right now, the default dispatcher is very useful for CPU intensive work. So things like data processing, image processing, things that that should usually be done with the default dispatcher. Now we have another dispatcher called the Iot, and this is their useful for network communications. Okay, And reading and writing file. So any input output operations should go through the Iot dispatcher, and then we have an unconfined dispatcher. Okay, so the unconfined dispatcher starts the co routine in the inherited dispatcher that called it. So if you have a co routine that works on that, say the main dispatcher and then you start another co routine as unconfined, it will start the co routine in the inherited dispatcher, which is the main. Okay, so we're not defining what dispatcher we want. We let the system decide for us. Now we have another dispatcher, which is the new single thread context. And this simply creates a new thread for us. It's for it forces the creation of a new threat. Now, this shouldn't really be used at often, because threads, as we've seen, are quite expensive. And, um, co routines are very, very light weight. So we should try to use co routines as they are intended, and allow the dispatchers to move them around from thread to thread. But sometimes you might want this situation. So it's good to know that you have this possibility. All right, so let's go ahead and run or try out some of this code in our project here. So let's go ahead and do a run blocking run looking here. All right, so let's go ahead and first trying to launch a co routine in our main dispatcher. Okay, so we have launch dispatcher's doctor may face. We're trying to run a co routine in our dispatcher. I'm gonna print line. Um mein, um, dispatcher thread is going to be so I'm gonna try to print out thread dot current threat dot May just to see which thread we are on when we are launching a dispatcher along a core team. All right, so let's go ahead and launch another one in our dispatchers. Dot dot That's a unconfined. Okay. And here we're gonna print line unconfined read is going to be expressions red dot Current . Read the name. Okay. I'm just gonna copy this part because we're gonna use it to look. Now the unconfined dispatcher has another particularity, which is that when the core routine is paused when it is resumed, it will switch threat Okay, so let's go ahead and try a delay. Let's say 100 milliseconds and then we're gonna print line again. Unconfined, Let's say to and paste the threat confined one here so we will see the threat being switched from the first time we we launched the cover teen. And then when we pause it and then we resume, we will see the threat being changed. Now talking about these threads doesn't really impact us a whole lot in our development of co routines, but it's usually good to know which thread you are working with when you have a co routine . OK, it's just part of kind of understanding, multi threading in Scotland and in Android in general. So let's go ahead and launch another one. And this time we're gonna use the dispatcher doctor fault. Okay. And then here we're gonna again see which threat it's running on. Some guys print line, default and paste these thread printer. Then we have a dispatchers thought I o Okay, frank line. I o. Okay. I realized I made a mistake here. Default. And then finally, why not? Let's go ahead and launch our new single thread context here. We need to give it a name. So I'm gonna say my thread. Okay, let's go ahead and print line as usual. New single thread context and paste the current threat. Right. So we are launching 12345 co routines with different dispatchers in different threats. So let's see which threats they are running on. I'm gonna run the coat. All right, So the first thing that we see is the error, okay? And that is the normal, Because we are trying to use the main dispatcher, and we are not allowed because in our they're grateful Scotland Project, it is not specified. If we were to run the same code on Android, that will work fine, because it will work on the main threat. But here we don't have a main street define. Okay, So I wanted to leave this year just to show you the error that you get. So something like illegal state exception model with the main dispatcher is missing. Okay, so we're not defining the main dispatcher, so we cannot run this year. Just gonna comment it out and let's go ahead and run the other dispatchers. All right, so there we go So we have our unconfined dispatcher. Okay, so we can see that unconfined one is running on. The main threat, however, were delaying for 100 milliseconds and I'm gonna find two is actually running on a different threat. You okay? So you can see that the code routine has shifted from one thread to another when it was resumed. All right, next up we have our default dispatchers dispatcher and that is running on default. Dispatcher worker, whatever that is. OK, then we have the io, which is running on default dispatcher worker too. So this is kind of internal too, um to Coplin too cold routine. So we don't really have too much of a control. Nor do we want control over which thread the cover itchiness is running on. We just know that the Iot dispatcher is specific for input output operations. Okay. And then we have our single thread context, which basically creates a threat specifically for our co routine. So here we have that the threat is called my threat. Now, like we said, this is a bit expensive in terms of resource is so you shouldn't really use it unless you absolutely have to right. So that is how you would use dispatchers to perform operations based on the type of operation that you have. 11. Async: All right. So a sink is basically another way to start a co routine. So sometimes when you start a cover team, you might need a value to be returned from that co routine back to the threat that launched it. Okay, so a think is over the way to do that. It is just like launch accepted in turns. A result. Now, the result it returns obviously sent its running in parallel. It cannot return the result immediately. So think about an operation like network communication might have an undetermined delay, but we still want to have that result that outcome at some point. Okay, So what basing does is returning results in the form of a deferred? Okay, so it differed is basically a promise that at some point we will be able to get a result, but it's just not available right now. OK, so it's a future promise of a value. Now, when we actually need the value, we have the await function. Okay. Now, importantly, this is a blocking call, and it's done on purpose, obviously, because at certain points, we do need the value. We cannot proceed without it. So we have to wait for that value to be available. So either the value is available straight away, which it will return immediately. If that's the case, or if the value is not available, it will pause the third, the current threat until it is okay. So we have that await call. So how do we use this? Well, it's quite simple. So let's say we have a suspend function that just gives us a random integer right now. We would have a a sink cold routine. So we have global scoped out chasing. This will just launch a coating that will simply call the suspend function, get random. Okay. And that will give us a deferred. Okay, so this is the object of type. Differ. Then we do whatever processing we need in that program. And then when we actually need the value, we have the dot await function. Okay, so this will pause the execution until the value is available for our main program. Okay, So quite, quite simple, quite intuitive. Were simply waiting for a value to be available. So let's go ahead and put this in our coat. So first of all, I'm gonna say, run blocking as usual. Okay? let's go ahead and define a function or rather, two functions that return us, you know, to values. So I'm going to say, suspend fun, get first value. Now this will return an integer and then first thing we're gonna do, we're gonna delay for one second, and then we're simply going to generate the value so Val value equals ran them. Okay, make sure you get the Coplin random dot next int, Let's say up to 100 then front line returning first value, dollar value, and then we have return value, okay. And then we have another suspend function, which is going to be very similar. Gets second value that will return into jerk. All right, that this time we're gonna delay for two seconds, we're gonna have a value equals random dot Next. Ain't Let's say this time to 1000. We're gonna print line returning second value dollar value here, and then we're gonna return value. All right, so we have these two functions that give us values. OK, so we want to call these in separate code routines, and then we're going to, you know, wait for these values and perform some operation. I'm just gonna add them together. So, Val, first Differed is going to be. They sink. Keep in mind. We are in the scope off. Run blocking. Okay, so this is will be get first value, then second deferred equals a sink. Get seconds value. All right, so we have our co routines. We have our deferred. Let's delay for a short while. 590 seconds. Then I'm gonna print line some message waiting for the values. That's print line. A message before this, Saying something like doing some processing here. Okay, Now, after we've done, we're done with the processing. Then we need to actually wait for those two values. OK, so I'm going to say, Well, first value is going to be first deferred. Dark await. Okay, So we are waiting for the result from the first Koubriti, which will take one second. Then second valued is going to be second deferred dot Await. Okay, The 2nd 1 will take two seconds, and then I'm gonna simply print line. The total is dollar. First, tell you for its value plus second value. Okay, so we're calculating this some of the two values. All right, so this is quite intuitive were just doing some processing. And then we're waiting for the 22 functions to return. So let's go ahead and run our coat. All right, so we're doing some processing. We're getting the first value after one second, second value after after two seconds, and then the total is for 85. So basically, they think is a way for us to retrieve values from qualities. 12. withContext: now a function that is very commonly used in co routines is with context. The basically, with context allows us to easily change context, basically easily switch between dispatchers. Okay, so if we have, let's say a let's think about a android application and we have, um, some heavy processing that we need to do on an image. Listen, right so we would do that in the default dispatcher. Then, when the outcome is completed, then we want to switch to the main dispatcher in order to published to show that image to our user, to put it on the u Y. Right. So we need a way to easily switch between context and the best way to do that, busy with context function, because it's very, very lightweight. Okay, now, like I said, it's very lightweight now the way we do that is Well, let's say we launch a default dispatcher, we do something here and then we want to switch to another dispatcher for, um, you know, different processing this case, for instance, network communication. Let's say so. Let's go ahead and do that in our code. I'm gonna run blocking. Okay, then, First of all, I'm gonna launch a quality in the dispatcher's. This patch ear's dot default. Okay, so here, I'm just gonna print line first Context dollar co routine context. Okay, So I'm printing out the context that we have here. Then I'm going to switch dispatchers to, let's say to the Iot. So with context, dispatcher's dot io and then I'm gonna print line the second context here. Dollar cool, routine context. Okay, so once that is finished, I'm gonna go back to my first context. I'm gonna say print line again. Third context is going to be the security. Okay, so I'm just starting the co routine in the default context. Then I'm switching to Io, and then I'm coming back to the original one. Okay, so let's go ahead and run the coat and see the output that we get from this print line. All right, So we have our first context, which is standard old standalone co routine. Whatever the name the system has given it, then we are switching the context so we can see that we have a different i d. Here. Okay. That's mainly what I'm looking for. I just want to show you the different ideas that we get, and then when we finish this, we're going back to our third context, Teoh to the same context that we had initially. So basically, it's a very lightweight way to switch between context, depending on the type of functionality type of processing that we need to do. 13. Exception handling: All right, so let's talk about exception handling in co routines. Now we know how to handle exception in a sequential program. Now, call routines are very similar, but they are slightly different in some areas. So exception behaviour depends on the co routine builders. So we already know that we have to call routine builders. We have launch and a think OK, launched generates a job. A sink will generate a deferred that will give us a value. OK, so based on that, the behavior changes slightly. Okay, So for launch, the sense launch creates a job hierarchy. Okay, the exception will propagate instantly through the parent child hierarchy and will immediately cause jobs to fail. Okay, so there is no, um no delay. No way to catch it automatically. Okay, So what we need to do is we need to use try catch inside the launch, or we have a structure called exception handler, and we will see what that means shortly. Okay, So launch basically automatically generates the exception and, um, causes all the jobs to fell in the hierarchy. Now you won't see the exception straight away. You will see the exception when you try to actually use the job or use the co routine in your main threat. So if you call join on the job, it will automatically join it to the main threat, and then you will see the exception. All right. Now, a think is slightly different. A think since we don't really have a hierarchy here, we just have a outcome. Theo. Exception is deferred. Okay. Just like the result of the sink, the exception is deferred and it is not shown until the result is consumed. So if we call a weight, then we will see the exception. If we never call await, we will never see that exception. Okay, so what we need to do in this case is used the try catch when we are using the await call, okay. Or of course, in the inside the core routine. We can also use that. So the difference is that launch propagates the exception through the job hierarchy immediately and kills the jobs. Um, a sink will only show you the exception when you call the await. Now, we have a way to handle exceptions in launch with the exception handler. Now what that means is we have this construct this class called core routine exception handler. Okay. And that will allow us to handle exceptions that may occur in the job. Okay, in a court routine. So here we have are not We have our that in my handler. Okay, that's what I call it here. And whenever an exception is thrown in the core team, it will be managed by the code in the core. Routine exception, handler. Now, if we are launching a co routine with the dispatcher and a handler, we can simply use the plus operator. Okay, so we are passing a default dispatcher here, plus a my handler. Okay, so that will work just fine. It will take both into account, and it will run on the default dispatcher and handle any exceptions that might occur here. So what I would like to do is put this all in code to see you, to show you a practical example of what this means. All right, So we have our function main here. I'm gonna run blocking, okay, just to create a context for our code routines, and then I'm gonna create valve job equals global scope dot launch. Okay. And then I'm gonna have print line throwing exception from, um job. Yeah, job. We don't have it. Another name for it, Right? So from job, and then here, I'm gonna just throw something like index out of bounds exception. It doesn't really matter what exception we throw right now. Let's go ahead and run it and we will see that. Actually, nothing happens, right? Because we're not actually using this job in anyway, So I'm going to right click, right and then throwing exception. We get this message, but we're not actually doing anything with the exception is not printed out. The way we could see this is when we try to actually join the Job corps routine to the current threat. So if what if I say job dot joint, then we will see the exception. So let's go ahead and run it. Okay, so we see that the exception has been thrown here and the program has finished. Now, the way to handle this is through, like we've seen to an exception. Handler. Okay, so I'm gonna have here a vow. My handler is going to be co routine exception handler. And here I'm gonna have this now This will give me a covert in context and throw a ball. Okay, so here I can do whatever I want with the throw a ball, which is going to be the exception. Okay, so I'm just gonna print line something like, exception handled dollar. Let's print out the message. Throw a ball. Terrible dog. Localized message. Okay, Songer, I'm handling this now. The way we use the handler is we pass it to the launch here somewhere, saying my handler. Okay, let's go ahead and run this code. So now we will no longer see that exception here. We have a exception handled. No. OK, let's pass a message here. Exception in Cortina, whatever the message you want there to be. All right, so we have exceptional handled exception and co routine. All right, so that is how you would handle exceptions for the launch launch operated. Now, what if we want to use a sink and we get a error and exception inside of a sink authority? Okay, So in that case, let's go ahead and create another co routine. I'm gonna have a felt different is going to be global. Stopped out pacing. Okay, Frontline. Now I'm gonna have throwing exception from a sink. Okay? And then he are gonna throw, Let's say arithmetic exception and I have here from facing All right, so I have this cooperating here. Now, again, Let's go ahead and run it to make sure that the exception is not thrown in our code if we don't do anything with differ, all right. So throwing exception for amazing, But we're not actually seeing the exception. So the exception is handled within the COE routine here. Okay, Now, if we have deferred dot Wait, then we will obviously see the exception. Because we're trying to use the value here. Okay, so we are seeing the exception. Now, let's go ahead and catch that exception with a try catch. Okay, Now, here I hav e of type arithmetic exception. And then I have a print line. No, I can't Arithmetic the exception. Let's go ahead and print line the localized message as well. Okay, so let's go ahead and run our code. Okay? So called charismatic exception from a sink. Now, this is how you would catch a exception. That happens in an A think. Okay. Either you have the try catch here, or of course, you could have the try catch here if you like to. And the my handler, the coating exception handler is how you would launched to you would handle gracefully exceptions from the launch way to start a color team. 14. Project intro: right. So let me just go through the project a little bit to kind of show you what this project is and how it is structured. Okay, So obviously, first thing, if you open up android manifest, you will have the Internet permission here. This is obvious. We need to communicate to dollar the image. We have a image. Your l here. If we copy and paste that in a browser, we will get this image of a dog. OK, so this is what we will be downloading, and this is what we will be processing. All right, moving on. Now we have a layout that has basically two elements. It has a spinner that will just show that something is going on in the background. And it has an image view that is currently hidden. Okay, so this will become a veil visible when we actually have something to display. And then we will hide the Progress bar. Okay, So progress and image to you in the background. Then we have main activity, which is quite empty for now. The great ally is exactly as it was generated. Nothing has changed. The only thing that I have added is the filter. Now this filter has a function apply on a big map, and it simply converted to a bit mapped out to another image. What this filter does it, It converts it to black and white. OK, so that is all that it does. It does handle some processing because it goes pixel by pixel to convert it into black and white. So that will take some processing power. And this is done on purpose so that we can apply. I wear, um, our co routine to it. Right. So we cannot do this in the mainstream. Or rather, we should not do this in the main threat. All right, so that is basically it. That is nothing else to this project. So you can see it's quite simple, but it is very useful for our purposes because here we will be able to apply that to cover things that we're gonna need first to download the image, then to apply the filter and then finally, Teoh, apply it to our image. You. So we will see that in the next video 15. Download an image: All right, so let's get started. Now. The first thing we need to do is we need to add dependencies for the co routines in our project. So to do that, go ahead and type double shift that will open up the search box. And here we will open up, build dot grade all. And we are looking for the app build up greater. OK, so open that up. Now. Here, down below in the dependencies. Here is where we need to add our dependencies for our co routines. So I'm gonna say implementation quotes. And that's gonna be borg dot jetbrains dot Scotland x colon Coplin X dash Cool routines Dash core. Okay, colon 1.3 dot zero Now, of course, when you're taking this class, you might have a later version of co routines. I do recommend that you use this version while you're building the project so that we don't have any inconsistencies. Right? If you build a project, you want to change the coaches to the newest version, try to do that at the end and see how that impacts everything. It should work this fine because usually the code routines will be backwards compatible but do use the wonder 3.0 version for the actual project build. All right. And one more. We need an implementation. That will be Orc thought. Jetbrains. Actually, you know what? It's exactly the same as this one up to a certain point. So I'm just gonna copy here everything until dash co routine. So copy that pasted down below and that's gonna be instead of core will have Android, and that's gonna be 1.3 dot zero as well. Now, to check that we have typed everything correctly, we will think now. And if you have any errors, the the greater will not find it dependencies. So that will throw you an error. So if you do have a never in this situation, go back and check the typing off your of your dependency here and fix any problems that might occur. So for me, everything went fine, and I now have co routines in my project. Now I'm gonna go to mine main activity. What we want to do here is we want to first load the image from the euro into a local bid map, and then we want to put that big map in our image view that we see here in Maine activity. We're gonna put it into this image here. All right, So the first thing I'm gonna do is I'm gonna create a function. Let's call this private fund. Let's say get original big map. Okay, now here. This is going to return a bit. Map. All right. Make sure you import the bit map class. They're all right. So here in this function, we're gonna go ahead and download the actual image. So I'm going to say you are l okay. Image the image you are. L Okay, dots, open stream, Doc. Use an insight. You I'm simply gonna return bit map factory dot decode stream it. Okay, so that will basically decode my stream into a big man that we're going to return. And you know what? It's actually easier if we just say equals, So we will simply return whatever is returned from this decode stream. All right, now, importantly, this is a network call. Okay? So we cannot do this on the main threat. So what we would like to do is we would like to open up a co teen scope and do that call inside the scope on the i o dispatcher. Okay, so first of all, I'm gonna create a variable here called Private Valve. Cool. Routine scope equals. So we're gonna create a call routine, sculpt, and here we're gonna pass first with their past the dispatcher's dot may. The reason for that is because we want to eventually put that image into our image. You okay? So we want to do that on the main dispatcher. Otherwise we cannot update the you. Why? From another threat. It has to be from the main. Okay, so first of all, we're gonna open up a main scope here. All right, so inside the on create function, I'm gonna say Coubertin scope don't launch. All right, So we're launching a co routine in the scope off the main threat. Now, here, we want to download the image. So we want to call this function. However, we want to call that function on the Iot dispatcher. Okay, So here, we're gonna have vell original differed. So you can kind of guess what we're gonna do here. We're gonna get a difference. We're gonna use the a sink call, and I'm gonna say here coverage in scope co team scope, not a sink. Now we're gonna pass the dispatcher's dot Io. The reason for that is it is a network communication. It is an input output call. So we want to do this on the isle dispatcher and here we're gonna simply call get original Big Mac. All right, so we have a deferred. However, if we want to show the image on the u I we have to have the image. Right. So we want to wait for that image to be available, so I'm going to save l original. The map is going to be original deferred dot Await. Okay, so we're waiting for the actual Bittman. Now, once we have that, we're gonna show it to the U Why? We're gonna put it in the image here. And for that, I'm gonna create another function private fund load image, and I'm gonna say bmp of type Dignam. All right, so what we need to do here? Festival progress bar that visibility is going to be reviewed up gone. Okay, so we're hiding the progress bar. Then image. You got loads. So the image you got set in its been we're gonna pass the BMPs here. And then finally, we need to show the image you so image, you duck. Visibility is gonna be view dot visible. All right, so we're showing the view as well. And of course, we now have the bit map. So all that's left for us to do is say load image original big map. And that should actually show the image. Now, keep in mind, we haven't actually added the filter. We will do that in the next video, but for now, we're just showing an image that was downloaded from the network. Okay, so that is done. Let's go ahead and run our code in an emulator. You can, of course, run it clean and show you what we have. So this is for my tests. Don't worry about that. All right. So that has finished launching. We can see the spinner going on in the background while the image is being downloaded. And at any point now, we should get the downloaded image to appear here. And there we go. So as soon as the image becomes available as soon as it is downloaded, it is filled in here. So what we have done here is quite important. Even though, you know it might be very simple as functionality, it's important in the way that we have done it. So we have done it using color teens to communicate through the network to download an image and show it on the Y. 16. Challenge: Alright, guys. So before we move on to the next video where we see how we apply the filter to our image I want to give you a challenge. Try this out by yourself, trying to once you have the original image, have another Cobra team that will apply the filter. Okay, filter you will find here in the filter apply function, apply the filter on the image and then display the sultan image to you are. Okay, So try that out yourself. See how you get on and then go to the next video where I will intimate that functionality as well. 17. Apply the filter: All right, so now that we have an image that is downloaded and shown to the U. Y, what we want to do is apply a filter to that image. And we've seen the filter that we have here in the object filter. We have applied on a source bit map, and that will give us the output here. All right, Now you can go into the details of how this is done, basically for each big. So we get the RGB, we average those RGB colors, and then we replace that pixel. Okay, so that is the gist of it. Now, this does need some processing. So what we will do is we will do this on a Coty, right? It's not a meself. A separate threat. It's a cover routine that will run on some threat in the threat pool. We don't really care which threat now, in order to do that first, let's have a function here in our main activities are gonna have private fun. Um, loads, filter, or rather, apply filter on a original bit Map of type, bit map. Okay. And that will simply give us filter dot Apply two original bit map. All right. Easy enough now that now that we have that, let's go ahead and call this in a core. Pretty. Okay, so here, after we have our original bit map, we're gonna say valve filtered deferred is going to be coverage in scope dot Basing Now, we need to do this on a dispatcher. Now, which dispatchers should we use? Well, this is processing that is done locally on the device. OK, so we might want to use the default dispatch it. That is the one that is needed in order to make the most of this kind of processing. So I'm gonna use to dispatchers default here, and I'm gonna apply the filter. Teoh, our original bit map. Now, keep in mind this is done after we have waited for the original Big Mac. OK, very important because we do need the original big man in order to apply the filter. And then we need to, of course, wait for the filtered bit map to become available. So I'm gonna say about filtered big map is going to be filter deferred dot Await. And then finally, what we want to do is we want to load the filtered bit maps here. Okay, so let's go ahead and touch, actually, be it. Let's go ahead and run our application and see the outcome. All right, So now we have a bit more waiting to do, because first, we're loading the image from the background. Then we are applying the the processing to that image, and then we are displaying, okay, so that processing might take a while. All right, there we go. So we have processed the image. Processing is quite fast because I'm running this on a very powerful laptop. So it's not. It doesn't take a while. If you have an older phone that you're like you could use for testing could run on that and see it take a little longer. Right? So there we go. This is the processing for this image. You can see it's black and white with a kind of a black background as well. So that's it. That is how you would use to co routines in different dispatchers to get the image, apply the filter, and then finally, in order to lower the image, we are using the main dispatcher here to load the image into the image here