Transcript from the "Requesting API Data" Lesson
>> So, the next step is to somehow download the data, create the API, okay, make sense? So, to do that, we are using our frameworks. So, going back to the companion website, here I have a Kotlin file for the API, okay? So again, this has to do with how the frameworks that I picked that I think were the simpler frameworks, because there are so many frameworks to do networking and also JSON automatic parsing.
[00:00:37] There are so many, I think this one is the simplest one, okay? So I'm going to create a new Kotlin class API. I'm going to paste this and now we will analyze what's going on. So first, we have an interface, CoffeeMastersAPIService. And this is how this library works.
[00:01:01] You create the function, okay, and we annotate the function saying that I'm going to get the service using the GET method, menu.json, on this base URL. This is actually the JSON that we're going to simulate. Look at it, so let me open Chrome because the JSON will look better here, menu.json.
[00:01:27] This is the JSON that we are going to consume. It has categories, each category has product. Okay, it's matching our data classes in Kotlin. Makes sense? So, what about this weird thing suspend? This is an advanced Kotlin concept. This has to do with something known as coroutines. So if you wanna learn something more about Kotlin tomorrow, go and learn about coroutines.
[00:02:01] Coroutines is a new mechanism in Kotlin, to actually make some kind of aising proming, some kind of threading. I don't wanna say that the coroutine is a thread, but it's kind of that, okay. It's a modern way, it's a different way to work with threading and multitasking. Anyway, that says that this fetch menu will actually be asynchronous, okay, that's kind of the idea.
[00:02:28] So, okay, we have the API. [COUGH] The next step, is to convert our DataManager into something new. We are going to convert this into something known as AndroidViewModel, okay? AndroidViewModel is another framework from jetpack, not jetpack compose, jetpack the general library. AndroidViewModel needs, so we are going to extend from AndroidViewModel, we are going to be a view model, needs an app.
[00:03:04] What is an app? It's a reference to the current app. So one simple way to do this is to receive this from somewhere else. I don't know where the app is coming from. We will need to receive that object somehow, okay? And we are passing that object to the superclass, to the AndroidViewModel.
[00:03:24] Does it make sense? Just that for now. So we're going to use AndroidViewModel that will automatically make our code work magically, okay? We convert this DataManager into a view model. So now, I can create a new function in my data manager that will fetch the data Okay, how to fetch the data?
[00:03:50] We need to call API.menuService.fetchMenu(). What is that? The function that I have just created, where? In the API Kotlin file, this one. But there is no code here. The code will be automatically be created by the framework. So I don't see anything, okay? I'm just saying, call that menu.json and magically retrieve me something, that's what I'm saying here, okay?
[00:04:23] So, what I'm going to do here is fetch menu. You can see here that little icon, that says it's a coroutine. So, here comes the part where we are not covering coroutines, but I'm going to show you this. I'm going to call something now viewModelScope.launch. And this one will go actually inside, like so, I need to import this.
[00:04:57] Actually, what you put inside this code block is in a coroutine. That is, it's a new thread, let's say. This is no 100% right, but let's say it's in a new thread. So we're running this in a new thread. Actually, I'm receiving the menu and storing the menu in my list of categories.
[00:05:18] Okay, like that. And the next thing that I can do is, remember the initializer block in it, that will be executed automatically when you create a DataManager, well, I can call fetchData(). So when we initialize the DataManager, we go and fetch the data from the API. Does it make sense?
>> I'm just thinking if it's asynchronous, we have to have another hook. I know what happens when zombie render or things like that or anything.
>> We don't need to do anything else, why? Because in a new thread, this is going and fetching the data, when the data is ready, it's going to change the menu.
[00:05:54] Because the menu is a mutable state, it will trigger the recomposition of my app. Make sense? Okay, there is still one missing point. No one is using DataManager, okay, at this point. So we actually need to somehow create the DataManager somewhere and connect it somewhere. So the only one that can actually create the DataManager, so DataManager needs the application.
[00:06:24] That has nothing to do with chatbot compose, has to do with standard Android application, okay, is activity. Remember that we have here something, let me, it is a function on creating activity and we have an app. Well, actually, this is the one that can actually create here, the DataManager, okay?
[00:06:51] And then we pass the DataManager through our composition, through our composables. So how do you create that? With this, we don't create it manually. We talk to a view model provider. Again, this has to do with a framework. Another framework that will let us make this work. We pass this, this is the current activity.
[00:07:13] Is like a reference to the current app, the current project. And we actually say that we wanna get a DataManager, And we need to pass a class by argument. In Kotlin, to pass a class by argument double colon, so when you pass the type as an argument, it's .class, and there are two ways to pass this, Kotlin class or Java class.
[00:07:47] Because two different things. If you aretalking to a Java API, you need to pass a Java class. And ViewModelProvider is a Java class. Now, we have the DataManager, but we need to do with the DataManager is to pass that to our app. And for that, the app needs to receive the DataManager.
[00:08:06] Makes sense? So in our app, We're going to receive a dataManager of type DataManager. Makes sense? Who needs the DataManager? Remember, the DataManager is the container for our menu and for our cart.
>> Order Page.
>> Order Page and menu page, right, because it needs the items to render those items here.
[00:08:38] So we are going to receive DataManager and also in Order Page, DataManager.
>> Why are you passing the class? Again, I'm sorry there review the class.
>> Why passing what?
>> The class, go back to the main activity.
>> Main activity, here, because actually we are not the ones creating the class.
[00:09:00] We're asking the framework, the framework is ViewModel. Again, we are just viewing the surface of ViewModel. And the ViewModel is the one that will actually play with multi-threading and making our state variables work. So it's the one that will make the magic. And in this case, we're not creating the class dataManager, we're asking the ViewModel to do that.
[00:09:25] So it inject its magic, and it's using internally reflection APIs to actually create my instances of my class and it pass the class as an argument.
>> Okay, does that make sense?
>> Yes, thank you.
>> Okay, so now we need to pass the dataManager, Like so.
[00:09:52] There are other ways to do this instead of passing an object through the composition, through the hierarchy, but this is the simplest way. So, any question at this point? Nope, I think there is an arrow here. Well, now we have problems with the previews, because they will need to pass the DataManager, okay?
[00:10:19] So for now, I can command those previews, yeah?
>> The coroutine that you're creating was that get. Is that gonna wait for that thread to finish before moving on to the next thread?
>> So coroutines are functions that can execute simultaneously. That doesn't mean that there are threads, so this is coroutines this is an enzyme from Kotlin, okay, that will manage that individually.
[00:10:48] So if you open five coroutines, that doesn't mean that you have five threads. Maybe they're all executed in the same thread and it manages automatically the execution of the content inside. So coroutine is a complex, let's say concept. That doesn't mean that you won't be able to understand that.
[00:11:10] I mean that you have just learned Kotlin for the first time a few hours ago. And it needs your brain to process first other things to get the idea, but it's kind of a mix between threading and acing framing. It's mixing both, okay? It's actually really powerful. So what it's doing in here is that, it's not like that coroutine will wait, okay?
[00:11:35] But it's not messing with my main thread. When the data comes from the network, it will automatically, I believe, my state. And when that happens, probably, my UI will elaborate. That's kind of the goal.
>> I mean, in this case, the user has to, I mean, because I'm thinking of something, the user can interact before things load, right?
>> Exactly, if you try to do network on the main thread, you may have problems like that. The only good news about Android is Android won't let you do networking on the main thread. It creates an exception. If you try to access the network in the main thread, there is an exception, network main thread exception to avoid that, okay, so you won't be able to actually make it work.
[00:12:24] So we work my code, I mean, I'm not doing anything yet. But just to see if some data quickly appears. Well, I can use the console to print something or in the menu, but of course, we are going to update this. I don't need the preview now, that is giving me an error.
[00:12:42] In the menu, I can, for example, put a text with dataManager.menu.count, count is the length of a list, okay? But it's an integer. How can I quickly convert this into a string? toString, or I can put this into any a string with an expression, with a template, okay, like so.
[00:13:11] Okay, I need to put this into an item, because the lazy column needs things with an item or items. Okay, and here, what's the arrow here? Count, now, list. The menu is the list of categories. Cut, cool, just to see if it's doing something, this is not the final goal.
[00:13:45] But this is not gonna work, why? Android applications, by default, are offline. So you cannot actually access the network. If you try to do that, you will get a security exception. So we need to ask permission, where? In the manifest file, in the AndroidManifest file. Here at the top, we go to AndroidManifest.xml.
[00:14:10] And this is an XML, it's really long, but in an empty place within the root element, we open and we need to add a tag uses-permission. Okay, the tag is uses-permission. And you will have a list of permissions that we can request and the first one is INTERNET access, like that.
[00:14:36] Okay, so that will add permission to Internet.