How to Make HTTP Requests With Ktor-Client (Cooler Than Retrofit!) - Android Studio Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome back to new video in this video i will show you how you can use ktour client-side many people don't know that's actually possible but yes caterer is not only a back-end framework with kotlin no it is also a client so a network line such as okhttp and we can use caterer to make network requests http requests to an api to get the response and now you might wonder why should you actually choose ktor and not ok http in combination with a retrofit which is a really good combination retrofit makes that stuff really simple however kmm kotlin multi-platform mobile is becoming more and more a thing so we can make ios and android apps with kotlin um at least we can share a very big part of our code and in km we have to we have to use cotton libraries if we want to share these across android and ios and ok http and retrofit are java and android libraries so we could only use that for km for the android side but we we couldn't share that logic um that also the ios side makes use of retrofit and that is why cater is is a really good alternative to retrofit to use for kmm projects because we can make network requests with a pure kotlin library which also works really well now if you don't use km we also don't use it here it still makes sense to take a look at kator because you might like it more than okay http and retrofit to make your network requests and especially if you watch some of my cater courses and you build backends in cater then it also makes sense to take a look at this client because it's it's built very similar as the server side i mean you will there will be some mechanisms you will you will face that you already know from caterer server side and this will just work together really well so first of all let's add the dependencies and i will go through these to explain what they actually do in our build.gradle app file i will paste this so quite some dependencies um let's go through these so we have our k2 or specific dependencies here which all make use of the current k2 version so k2 client core just the core functionality i think that's clear android specific functionality because we can also use the cater client as i said for ios for example then we would need an ios dependency here we have the kgo client serialization that will be important to serialize our data so if we want to post json data to an api or get json data from a response into a data class in kotlin then we will use the kotlin x serialization plugin to actually serialize and deserialize that and because i just want to show you an additional dependency here i included the logging dependency that's not needed to make the actual calls or get the responses but it will log your everything the client actually does that's really helpful actually to to debug your your client your network request it will always print the whole request and responses in the console so that you can easily debug that and see where maybe something is going wrong and that's also just a dependency here that's needed for logging then as i said we will use carton x serialization to serialize the data in retrofit we often use json or jackson or marshy but those are also just java libraries that we don't want to use in km so i just show you the the real km way here so we will also just use a serialization library that is fully written in kotlin which is called an x serialization for that serialization library we also need to apply a plugin up here which is this of course you can find all these dependencies and plugins down here on my github repository just check the description and one last thing we need to paste is to actually find this plugin we need something in our build.gradle project file and that is just this class path here without a cardline version then we can click synchronize now close these two gradle tabs and actually jump into coding and i will see i will show you how i would now structure creating such a cage or client to yeah make make network requests in a quite clean way so first of all this will be the api we use here not a real api just a placeholder api that is used for testing we are not working on a real project here i just want to show you how to use k-tour client-side and maybe if you like this video i will also soon show you how to use that in a project that's just a placeholder api you can use it comes with all different http methods here we can post we can get we can put patch delete and we will just make sure we will make use of this posts endpoint here which will just deliver us with a hundred posts which is just sample data just learn if so nothing yeah similar so that's the json response we get that's just one post with a title and a body and some ids in a list and that endpoint will also have a have a post method so we can actually create new posts just to show you how that also works with kate or client so remember that url jsonplaceholder.typiccode.com you will also find that down here in this description so now we can actually jump into coding first of all i will create a package here called data.remote and in that remote package i will create another package called dto data transfer object so just the data classes that represent the what we actually get from our api so let's create that you will see what that does we can create a new kotlin class a file in here and i will name this post response so that will be the the response we get from the api when we create a post that will be a data class it will contain the body so we have to name it the same way as in our api just this tile body title id and user id here so that will be one data class then the title valve id is an integer here and value user id and it really just random data here and if you haven't used the the kotlin serialization plugin before when we use that we also need to annotate the classes we want to serialize in the end without serializable so that way the kotlin plugin actually knows hey that's a class we want to serialize now we want to do the same for the post request which will be the same and it just won't contain i think an id or user id i think just the id so when we actually create a post with that api then it will respond just with a post we create it and it will give us it will give it an id so it won't actually do anything server side or so but it will just simulate a post request so we can in the end just take this post response copy paste it and call it post request and just remove the id because the id comes from the server in the response the next step is to actually create our api so we need to define which different functions we we have for api that we need to access the endpoints in retrofit we just created an interface for that we wrote some annotations like a get request we specified the url we specified some creative parameters also with annotations and retrofit did the rest for us in ktor we don't have that annotation processing instead we need to kind of define our own interface for that which isn't really much harder to do so i will show you how to do that we go to remote new carton class of file and well the naming is a little bit up to you you can name it like hosts api you can name it posts service which is a common way of calling these api services that's how i will do it and we'll create an interface here it's not mandatory to credit interface we could also directly create the implementation but because i want to show you a good structure here that is how i would usually do that in my projects it just allows you to more easily test your api because then you can create different variations of that post service so the step in this interface is really the same as if we would create um an api with a retrofit we just defined the functions we have and we just leave out the annotations what do we actually have on the one that we have a get function to get the list of posts and on the other hand we have a post function so to create a post let's create these two functions those will be suspend functions the the ktop client does everything with coroutines i mean it's a cue it's a pure cotton library that isn't a surprise that it uses curtains i'll call this get posts and it will return a list of post response and then we do the same for our create post function that will now take the post request that is the data we we serialize to json and sent to the server and then get the response that this function will return first response it could be null in case something goes wrong so we make it nullable now that's already for the interface you can see it's simpler than a retrofit interface because we don't need these annotations instead for like the the url maybe some headers maybe some body content we we actually specify that in the actual implementation of that interface which we didn't need to do with retrofit with cato we do need to create an implementation of that interface so when i go to remote new kotlin class or file and we call that posts service implementation that will be a normal class and it will implement our posts service interface then you will see we need to implement our two functions we can press ctrl i ctrl a and enter to do that and now here we actually need to make the actual network call using our cater client well where do we get that from in the service we just injected in the constructor so just private val client is of type http client you can see that comes from iocate or client that is what you want to pick and that will be the object we make our network calls with so then for get posts what do we do it's really simple you will see how that works we just return client dot get we can use this lambda way of writing that and here we just have a normal builder in which we can specify some more data about that about that get request such as the url for example that's necessary here but that is already it we don't even need to know more about this request you don't need to attach any headers any body content any query parameters but if we would need to do that we could do it in this lambda block so we can specify the url the endpoint where this request should go to so in retrofit we had this um retrofit builder in which we just specified a base url here we don't have that we can still do that which i think is helpful and for that i will create um another constant file here which i will call http routes and in here i'll just specify the base url can be a private const well base url and that will just be https jsonplaceholder.tipiccode.com and then we can specify just one content for each single endpoint we actually make use of and in our case that's just one which is um the post endpoint and we can create that using our base url slash posts now we can just use that uh singleton here to get access to our endpoints so in our post service implementation we can then specify the url to http routes posts and that's already it so in case you would need a query parameter you could simply do that with parameter specify the key and the value if you would have path parameters then you would directly do that here in the url so if you would like to oops i mean here if you would like to have something like the post id here and you would then access i don't know a user or so then you would need to manually manually create that url and just replace that id with whatever you want but for query parameters you could also just attach this to the url but there is also a function as you can see to do that you see it's it's super simple now to make a get request with that just request two lines of code if you if you write it in one line even only one line um for the create post function we need some more lines not that many but it's also very simple and something actually forgot and i also want to show you if something goes wrong we need more lines then we want to just surround that with try and catch but that's also the same with retrofit so if something goes wrong here meaning the server responds or the response code that does not start with a two because the the response codes that start with the two usually mean everything went well if it does not start with a two like the three x x four x x and five x x then something went wrong and for each of these cases cato will throw an exception so on the one hand we have a redirect response exception just to show you how you can actually distinguish these you can also just uh catch a general exception and say hey something went wrong so that redirect response exception will be thrown for three xx responses so when that is the the response code we can print like the error and here we can say e dot response um status that description for example and then just return an empty list and we can copy that catch block i just want to show you the different responses the different exceptions we have here this would be client request exception and this exception names even already tell you what they what they will be thrown for so that will be thrown when there is some kind of redirect issue that will be thrown when there is an issue in the client request so when we for example post some data that is invalid that the server doesn't know what to do with then it will respond with the forex x code and then we have something for the 5x codes which is server response exception so that means the the client request was okay but still something server side went wrong maybe the database crashed or yeah something unexpected happened and the server just ends up with for example internal server error then we would catch that here and that's pretty much it you can of course if you don't have internet connection or so also have a general exception down here and yeah just also print that here we don't have that status description we will just print the message if you don't need that fine grain control here then you can also leave these away but yeah if you if you want to give your users maybe some kind of error message that is meaningful you should catch different exceptions here and if you also want to forward these error messages here to another layer of your architecture then yeah just just check one of my architectural videos that i use a resource class that i wrap around this response object this return object and with this resource class we can just distinguish between success and error case and also attach corresponding data but here for this simple tutorial i just decided not to do that and just have a print line statement now for the create post function we can actually just copy this this whole thing here because it's very similar all that really changes is this piece of code here because now we don't make a get request and said we make a post request this one here you see we need to specify a type which will be the response type so what this what the server will respond with which will just be post response and then here yeah we will leave the url as it is we will call the same url just with the post request this time just two differences here for post requests on the one hand we want to attach a body we want to attach our post request data that we want to post to the server and on the other hand we then need to assign the content type so we need to we need to tell the server hey we're actually passing json data here so please just as you know how to how to deserialize that data server side so i'm going to say content type content type application.json that's really easy that will then attach a header for us and we can say the body it's just our post request and it will automatically be parsed to jason and attached to this request then we get some more errors here because we return an empty list instead here we want to return null in that case here here and here like that and then all the errors are actually gone now one thing that's really missing is we need an instance of this http client so we need to create that where we just defined some some basic information and some basic features this client should have and where do we do that well we can do it directly in our post service that we create that um that we just have a create function in a companion object just similar to just a factory pattern um in case you use dependency injection which i strongly suggest you in a real project then i would maybe still use this factory array of instantiating that but then you of course provide the corresponding inter the corresponding instance in your module and your dagger module or so whatever you use for this simple tutorial i will create a function called create which will return such a post service and here we can just say return posts service implementation because that is what we want to use for our production app and we need to pass a client for this client we need to say http client and this now takes the so-called engine so actually yeah it's kind of what drives this client because there are different engines for different platforms we're on android and that is also why we included this this client android dependency here that comes with this android client so that this actually works on android here we just pass android this from iok to our client engine android press enter input that and then we can configure that client in this lambda block now in this lambda block we can install so-called features if you know k-tour server side you will know these features so what can a feature for example be a feature could be a logging that we log network requests the feature could be json serialization a feature could be authentication all that stuff is a feature in kturb and it's it's really cool because we just need to include a dependency that will come with a feature and we just say install logging boom and we have logging functionality it's really that easy if you then want to configure that feature you can also do that in another lambda block like we could set the log level for example to lock a level all so just we lock everything just to show you how you could configure that that's not a necessary feature because it's just for logging it's a helpful feature but one that is necessary here for us is actually the kotlin serialization plugin that we apply that that it automatically passes this post request for example to json and attaches it to the body and that it also automatically passes the response here from this get request to a list of post response so we want to install the json feature and here we can again just configure that we want to assign a serializer so that feature just says okay we'll be able to serialize json data and deserialize that but we don't specify yet how we want to do that with which plugin with which to dependency or library so we could use json here we could use marshy but what we use is actually the carton x serializer so we can say serializer is equal to new kotlin axializer which you could also further um configure here which we don't need and that's already it that's how we create our instance of a caterer client then the rest will be the main activity just that we make the request and populate our ui with that so in here just an empty compose project i'll just uh put my client in here and don't do that in a production app you want to use dependency injection in the view model um [Music] client will be would actually just be equal to posts posts service come on first service create then to make the network request i will use the produce state function so we can get the post list here by using produce state we can define an initial value and a producer if you watch my compose basics playlist you will know this function we just define an initial value that will immediately emit here as a state so that will just be an empty list of a list of posts actually post response and the producer will be a function a creatine scope actually in which we can call curtains so suspend functions and actually assign new values to the state when we get the results of these functions so we can say value is equal to um post service how did i call it client yeah let's call it post service it's not a client or just service so we can say service get posts and when we have the result we assign that to the value so to the value of that state that will change and it will recompose our ui i won't implement any mechanisms here to post something i still wanted to show you how you can write a post function with kate or client i mean this one here i've tried it out trust me it works you can also try that and see the logs or you just uh yeah really implement the real app and try that out there just for that here we only just use a laser column to show the content here we all have an items block using this overload here which will be posts value and in here we what do we want to do we want to have a column we can give it a little modifier modifier a dot fill max width and just some padding of let's say 16 dp 160 p import dp and then just having two texts here to display the title and body so text edit.title font size let's set that to 20sp for the title having a little bit of space with let's say height of 4dp and then we are going to have another text for it dot body and the size set to let's say 14 sp and that's it the only thing that's missing is the internet permission so in our manifest we want to add that here use this permission internet and there we go we can actually now launch our app and try that out so let's see it's installing and yeah there we go our result from our api is just a list of these sample posts so it seems like everything worked if we take a look in our console then we will see the the logging stuff here you can see we we get the whole response because we set the log level to all and if we scroll a little bit up then [Music] here we also see the other data so like headers that were attached um what else like the urls here what type of request it is the response type it's very helpful if you if you have an issue with your api and your responses and you just want to debug that i would always throw in that logging feature and just remove it before the production build so that is it for this video so i personally will probably use this more often in future also for non-km projects just to have that in mind that eventually i will adapt this app to came in future so i i will try to design apps in a kotlin only way as much as possible because yeah that way i stay i stay flexible and when i want to make that multi-platform then i can do that and i don't need to rewrite my whole app i hope you liked it if so then you will also definitely like my free email newsletter i will send you regular kotlin android and architectural advice right into your inbox so to subscribe to that for free you can check the link down below and i wish you an excellent day see you next video bye bye
Info
Channel: Philipp Lackner
Views: 6,469
Rating: 4.9806294 out of 5
Keywords: android, tutorial, philip, philipp, filipp, filip, fillip, fillipp, phillipp, phillip, lackener, leckener, leckner, lackner, kotlin, mobile
Id: 3KTXD_ckAX0
Channel Id: undefined
Length: 26min 49sec (1609 seconds)
Published: Sat Oct 02 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.