Making web service calls to RESTful web services can take quite a bit of code, but there are some great tools available that can make it a lot easier. One of these is an open source library named Retrofit, created by the folks at Square.
- [Instructor] Making web service calls to RESTful web services can take quite a bit of code but there are some great tools available that make it a lot easier. One of these is an open source library named Retrofit created by the folks at Square. In this example, I'll be working with a JSON-formatted dataset and you can find it at this web page. Each item in the JSON dataset has a number of values. There's an item name, a category, a description, a price and so on.
And there are many different values in there. Now, my goal is to retrieve this data in my Android app over the web and I'm going to use Retrofit and another library called Gson to do it. I'll start by copying this URL to the clipboard, then I'll go back to Android Studio and then in my base package, I'll create a new Java class and I'll name it MyWebService. The kind of file I'm creating won't actually be a class, it'll be an interface and it won't implement any other interfaces.
Within the interface, I'll create two constants. The first one will be BASE_URL and I'll paste in that string. Then I'll take everything after the BASE_URL and cut it once again to the clipboard. Then I'll create a second constant and this one will be named FEED and I'll paste that value in there. So, now I have all the information I need to provide to Retrofit. Now, the next step is to actually use components from the Retrofit library and before I do that, I need to add a permission to the manifest and add dependencies to my Gradle build files.
I'll go to my Android manifest. In order to make the request, I need the INTERNET permission. So, I'll add a uses-permission tag and I'll select android.permission.INTERNET. The INTERNET permission is a normal permission and so, you don't have to add additional code to your application asking for permission at runtime. I'm done with the manifest and next I'll go to my Gradle build file for my app module. Now, I could enter the dependencies manually but there's a faster way.
I'll go to my Project Structure dialog to my app module and then to the Dependencies tab. I'll add a new dependency, I'll add a library dependency, I'll type Retrofit and click the search button and I get a bunch of items here. I'm going to use the core library initially and on my screen it appears at the top. It might be somewhere else on the list on yours. Look for com.squareup.retrofit2:retrofit and then use whatever the version is that appears.
I'm using version 2.3.0. I'll select that and click OK. And that adds the dependency down at the bottom of the screen. Now, I need one more dependency and I'm going to duplicate this line and then here I'll replace Retrofit with converter.gson and this will incorporate the Gson library. Notice that I'm using the same version number for both of these dependencies. I'll resync Gradle and now I'm done with the Gradle files.
Now, I'll come back to my web service. Now that I've added the Retrofit libraries to my application, I can create an instance of its component, Retrofit. I'll start typing Retrofit and it's a member of the package Retrofit2 and I'll name it Retrofit and I'll instantiate it with a builder object with new Retrofit.Builder and from there I'll call the method BASE_URL and pass in that BASE_URL.
Now, I want to tell Retrofit how to convert the data and I'm going to use something called the Gson converter factory. I'll call the method addConverterFactory and then I'll pass in gsonConverterFactory.create. And finally, I'll call the build method and now I have a Retrofit object I can work with. The next step is to define the different calls or methods that I want to execute and I'm going to add a get request that retrieves the entire feed and doesn't do any filtering or sorting, I'll keep it simple.
I'll use an annotation named GET and make sure you're using it from Retrofit2.http and then pass in the FEED constant. Make sure that you've imported the GET annotation. After the annotation, add in a call object. The call object uses a generic type and I'm going to add something called a DataItem. Now, I've cheated a little bit. In my application I already created a DataItem class.
It's under the model package. It's a really simple class. It's just a POJO class with a number of private fields and getters and setters and a two string method. There's nothing unique about this class for Retrofit. It's just a standard POJO. I'll come back here and I'm creating a call object that has an array of DataItem objects and I'll name this method DataItems and just like the GET annotation, make sure that you've imported the call class.
I'll clean up some of this code and now this new interface is ready to use. I've defined the location of the feed in the BASE_URL and in the FEED address and I've created the Retrofit object. Then I created my particular call that I named DataItems and I'm basically retrieving all of the data in whatever order it's already in. Now I'm ready to do some work in the MainActivity class. Network communications such as web service calls can't be made on the activity's main thread.
It has to be done in a background thread, so I'm going to set up an async task to handle this. I'll go to the bottom of my MainActivity class and down here I'll declare a new private class and I'll name it WebServiceTask and I'll extend the async task class. The async task class has three required generics, the parameter type, the progress type and the result type.
I'm not going to be passing in parameters and I'm not going to deal with progress, so I'll pass in void for both of those but then for the result, I'll set that as an array of DataItems. Make sure that you've imported the DataItem class because it's in another package. Now, when you've finished creating that declaration, there will be an error condition and I'll use an intention action and select implement methods and choose doInBackground. And this is where I'm going to make the request.
I'll start right here. I'll create an instance of the MyWebService interface. I'll call it WebService and I'll get its reference by calling MyWebService.Retrofit.create and then I'll pass in the class definition of the service, MyWebService. And because I'm not creating the WebService myself, I'm letting Retrofit do it, I'm passing in the class property. Next, I'll define the call object.
I'll create a call object with a data type of DataItem as an array. Once again, I'll import the call from the Retrofit library. Make sure you choose call from Retrofit2 and not from any other packages. I'll name it call and then I'll get its reference by calling webService.dataItems and now I'm ready to execute the call. I'll put this code in a tri-catch block. I'll say return_call.execute.body.
Then I'll add a catch block that looks for IOException and if I get into this code, first I'll log the error message with e.getMessage and then I'll return null. And I'll get rid of this last line of code. It won't be needed anymore. So, that's how I'm going to execute the WebService call in a background thread using the WebService task. Now, when I return this, I'm still in that background thread. I need to handle the return value now in the foreground or main thread and to do that, I'll override the method onPostExecute.
It receives the array of DataItems. And here I'm just going to output the information that I received. I'll create a forEach loop and each time through the loop I'll be working with the DataItem object. I'll name it item and I'll be working with the array that's named DataItems. And that's the argument that's passed into this method. Within the for loop, I'll call the log method and I'll pass in item and I'm able to do that because the DataItem class has a formatted two string method.
I'll call it explicitly and so, there's all the code I need for the async task. I have background processing to make the call and foreground processing to process the result. And now I'm almost done. I'll come up here to my runCode method. After I've cleared the log, I'll execute the call like this. I'll create an instance of my async task class, WebServiceTask, I'll name it task and I'll instantiate it with the no arguments constructor.
Then I'll call task.execute. If I were passing any parameters into the WebService, I could pass them in here but the way I've set up the WebService there are no parameters to pass and now I'm ready to test my code. When the app appears, I'll click the run code button and there's the data returned from the WebService. You can do a lot more with Retrofit including filtering and sorting data before you return the data to the rest of your application.
Take a look at the examples and documentation on the Retrofit website at square.github.io/retrofit.
Skill Level Intermediate
Q: Why can't I earn a Certificate of Completion for this course?
A: We publish a new tutorial or tutorials for this course on a regular basis. We are unable to offer a Certificate of Completion because it is an ever-evolving course that is not designed to be completed. Check back often for new movies.