Retrofit Setup - MVVM Pokédex App with Jetpack Compose - Part 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome back to a new video in this video we will set up retrofit so our library to make network requests so we are actually able to make these api requests to our pokey api which i showed you in the previous video you can see i opened that here in chrome that is just pokey api dot co that is an api that does not need any api key or authentication instead you can directly use it as you can see here you can just query a specific pokemon for example ditto or charmander like this one submit and that will be the corresponding api response here what we want to do here and what we want to start with is when using retrofit and especially when using json as we do in our project here if we remember we have that dependency this converter json which basically just takes the incoming json data so json data is this data here in text form and it will convert that to kotlin data classes so of course with data classes we can deal in a much easier fashion than with such a string here but to actually be able to convert these json responses using json to our kirtland data classes jason needs to know how these data classes look like and for that what we will do is we will take all that response stuff here copy this that is actually not that good um we want to click on direct link to results here and that is the raw json response here we can oops didn't want to do that we can simply hit ctrl and a to select everything ctrl c to copy that response and then we want to go back to android studio create a package here in our root package right click new kotlin class of file a package of course not a class this one this will be our data package inside of that data package we will have a remote package for api stuff and in that remote package we will have responses package in that response package we will then put all the different data classes that json can actually parse to from our api response and the disadvantage of this api here is that we get quite a lot of data here in a single api response that we are actually not interested in but that is something we just have to deal with here because we don't have any influence on that api and this api is still one of the best pokemon apis out there so after this course you can definitely extend this app because you have so much data in your app that we don't display yet and won't display in this course but still we need all these classes here in android studio so let's get back right click to responses and you can see i have a plugin installed called kotlin data class file from json if you don't have that plugin you want to hit ctrl alt s to open your android studio settings you want to go to plugins go to marketplace and search for kotlin adjacent to kotlin class this plugin you can see i have it installed if you don't have it installed click install restart android studio and then you will also have that option as i do here and that will basically just take in an uh json string here which i copied from that website you can see that has 11 000 lines of code and then we need to give the root class for our response a name and this plugin will generate all the remaining classes for us inside of that responses package and those will actually be a lot of classes here i will give this root class the name just pokemon because this request here represents a single pokemon you can see this is charmander here we get a url to that pokemon and we get all the data related to charmander so that will be the data that we need to query when we click on a pokemon detail view so we hit generate and then it will take a little moment and you can see it generated the classes um still doing all that adding files and you can see those are a lot of classes here but that was only for our first response which corresponds to single pokemon we also have a different kind of response which doesn't bring as many data classes here don't worry but the other response we get actually corresponds to the list of pokemon which displays on our main screen so we go back to google chrome to our pokey api main website here we can actually do this here as well we just want to remove the pokemon name from the url so just this url slash pokemon hit enter and you can see this gives us a list of pokemon and urls to these corresponding pokemon you can also see this response is much smaller than the response we had first because we get these pokemon paginated here you can see we have a limit of 20 so we get 20 pokemon at once and then when we scroll that far we can just load the next 20 and so on so again i will hit ctrl a and ctrl c go to android studio right click responses new kotlin data class file from json paste this you can see only 87 length this time and not eleven thousand and i will give this a name of pokemon list and click generate and you can see now only i think two more classes came into our package now we can collapse that because it's quite big and actually set up our api our retrofit interface in which we will define the functions how we can access our api so in our remote package not in our responses package we will create a kotlin classroom file select interface call that pokey api and press enter now in case you're not familiar with retrofit the way we do this is instead of this interface we will just specify the functions with which we will access our single routes from our api so we will have two functions here one function to get a pokemon list and one function to get pokemon data basically for the pokemon detail view so what we will have here is we'll have a suspend function because that will be executed asynchronously in accurity called get pokemon list and now we want to be able to pass parameters to this function to on the one hand assign the page size so how many pokemon we load at once and on the other hand we want to define the offset so from which pokemon we basically want to start so for the first call we will just have an offset of 0 load the first 20 pokemon then we will increase the offset by 20 so we will load the next 20 pokemon and so on and in retrofit or rather in http we do this using query parameters which we can use with this add query annotation which we can import here and do it like this we don't want to import this room query parameter here this room dependency instead we want to click on import we want to import that from retrofit not from room don't do this and in here we specify the name of the query parameter which is a limit in this case call this limit this is an integer so just a page size and we will have another query parameter called offset which will also be an integer and then this function will simply return our pokemon list and now with that we haven't told retrofit yet to which route this request should actually go and what kind of request that actually is so we do that up here we annotate this function with at get because that is a get request we want to get data we don't want to post any data or update any data and here we specify a string which is the part of the url this request should go to so we will specify a base url in this video which will just be the first part of your url that is basically always the same and let's just see that so our base url would be this and our request in this case to get this list of pokemon would then go to the base url and this pokemon here so what we pass here is just pokemon and then we will write our other function to get a specific pokemon and the data for it also suspend function get pokemon info i will call it and that will be a get request as well this will go to as you can see here we have that before charmander this would give us the pokemon info for charmander so now this is not a query parameter that is what we call a path parameter in http because the parameter charmander here we want to get the data for germander or for any other pokemon is part of the actual url and it's not a query parameter and because of that we want to use pokemon as a route slash and because the pokemon name is a variable here basically that can change for each pokemon and for each request we make we specify that here as our own path parameter and then we can say at path here we want to replace the name parameter here in our ul with the name we pass here as a parameter so whatever we pass for this name will be inserted here in our url and that will then return a pokemon and now i want to create our actual repository in which we'll make the network requests um i will do that in its own package let's create that repository package and in that we will create our proki mon repository and usually you would create an interface here for that repository and then let our real repository implement that interface which is good for testability of our application but just for simplicity reasons here i will just make this a class and yeah we won't have any testing here in this playlist this repository will then be injected into our viewmodel later on and it will be scoped to our activity so it will live as long as our activity does which is just the same as our application's lifetime here because we only have a single activity but we want to annotate this with activity scope and then inject dependencies into the constructor of this repository because in here we want to get access to our actual api instance so private val api of type pokey api so in here we will have the actual implementation of our api rather of making the network requests on one hand we have our suspend function get pokemon list which will take the limit and the offset both of type integer it will return our pokemon list response type and in here we can then get the response using a try and catch block so we want to catch exceptions in case something goes wrong for example when the user is not connected to the internet we will make the request using our api a dot get pokemon list passing our limit and offset and catching any exceptions here now we actually want to be able to somehow tell our viewmodel later on in our composables about errors that happen here so how can we actually do that for that i will use a common class i use in all of my projects which is called resource class that class will be used for on one hand for error handling for success handling and for loading handling so it will be a generic wrapper class around the response type here which now sounds super complex it's actually super easy let's do that in our util package which we don't have yet let's create that util and in that util package we create this resource class if you know my playlists you know this recess class that is a sealed class if not don't worry i will explain it so that will just be a generic clasp with a type parameter t here that means we can wrap this around any object we like and it will on the one hand take a data parameter of this type t which is null by default and it will take a message parameter which is of type string and nullable and nobody thought and now in here we can define different versions of this class basically for each state our response can be in so on one hand we can of course have a successful response so we can create a class success also type t and that will take a mandatory data parameter here of type t and this time it's not notable because when we get a successful response we also know that we get data that we want to attach to that resource class here so the data will just be our pokemon list in our case in this class we'll just inherit from resource of type t and for that we will then pass that data here and now for the message and we get an error here data heights member oh we don't want to make this a val because we can already access this data here by its parent class otherwise we would need to override it here now we want to have we can duplicate that ctrl d now we want to have an error state as well so if something goes wrong with our request and response this time passing data is not mandatory because if we get an error and something goes wrong we don't know if we have any data to attach usually we don't have that so we want to make this data per meter nullable and null by default but what is mandatory now is a message because when we get an error we want to tell our viewmodel and our composables about what actually went wrong and then also pass that data and that message here and finally we will have a class loading here which will take only an optional data parameter and that will just be emitted initially so we can display a progress bar and then when either error or success is emitted we can hide the progress bar again so resource.t and pass our data and that class which now looks quite complex if you're not that familiar with generics it's super helpful you can use that in every of your projects and i'll show you how what we want to do is we want to wrap this response to this return type into such a resource class so we input that and say resource of pokemon list and now in case we catch an exception and something goes wrong with our request we can simply return resource.error and here we can just pass an error message what went wrong and i won't do any detailed error handling here i will just write n unknown error occurred you could do this error handling here in much more detail but i won't do this here in this rather simple playlist and if we didn't catch an exception here that means everything went well we can simply return resource that success and now we need to attach data of type pokemon list which is exactly our response so the result from this api call so we pass response here and that is already it for this get pokemon list function let's do the same for our other function copy that and paste it down here which will be called get pokemon info this will take a pokemon name so the name of the pokemon we want to get the info for and the data that will return a resource of type pokemon this time because this time pokemon is a return type of our api call here we pass api get pokemon info and pass our pokemon name and that is already it for this function and now the last step for this video is to actually provide our api in our repository in our app module just to tell daggerfield hey these are the dependencies we want to be able to inject into our classes and specifically view models in our project here we do this with so-called provide functions so that's the naming convention we call them function provide pokemon repository for example and that will take our api because to construct our pokemon repository we need our api type pokey api and that will just return our pokemon repository and we pass our api and then we can annotate this with at singleton because this repository will be a singleton and with that provides to just tell daggerfield that this is a provides function and we also want to have another function provide pokemon pokey api i called it to just provide our actual api a retrofit instance with which we can then make the network requests here in the repository and that will return our pokey api and here we can just return retrofit.builder we want to add a converter factory which is our json converter factory that creates so that will convert the json code to your data classes i'm going to give the base url for which i will create a contents file in our util package cotton class constants select object and we create a console base url which will be https pokey api.co slash api slash v2 i think it is like this and then we can pass that here for our base url and input that we also want to call that build because that is already it and dot create where we can specify the api interface so pokey api double colon class java and then finally annotate this with singleton again and with provides and that is it for this video for setting up our api so now we are ready to actually make network calls in the next video we will then begin to write our ui so all the composed stuff and yeah i hope you enjoyed this video i wish you an awesome day and i hope that i will see you on the next video again bye bye
Info
Channel: Philipp Lackner
Views: 29,401
Rating: undefined out of 5
Keywords: android, tutorial, philip, philipp, filipp, filip, fillip, fillipp, phillipp, phillip, lackener, leckener, leckner, lackner, kotlin, mobile, pokedex, compose, jetpack, android compose, android ui, mvvm
Id: aaChg9aJDW4
Channel Id: undefined
Length: 21min 42sec (1302 seconds)
Published: Tue Apr 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.