Scratching the surface of Android's new Data Binding Library and Retrofit - Part 1

Scratching the surface of Android's new Data Binding Library and Retrofit - Part 2

Hi eager android developer, welcome to the Part 1 of this two part tutorial series. In this part we'll just be ready with data and environment setup to work with data binding in the next part.

Full source code of this project will be found here.

It was a long time ago android started it's journy. Android app developers were happy building simple apps. But as the time go the complexity of applications started to grow as well as software maintainance nightmere. Everything we had to do is writing so much boilerplate glue code between View and Activity. Activity got everything to control and view didn't know about the model. Activity knew everything and that's where strong coupling introduced.

In today's world it's quite impossible thing to develop large scale apps like that even a simple idea can be complex enough to maintain if we write code this way. There are some really great architectural pattern that can help us to write clean code such as MVP. But we've really needed some initiatives from google to make the development life easier and at last they heard us. Android data binding now at your service to rescue you to write less glue code but do more with loosely coupled View and Activity. Though it's in beta but we can hope it'll be stable soon. So let's scratch the surface.

Our target is to build a simple application which will show some recent movies in a list and we'll use a REST Api for that and we'll use Picasso for loading images from network.

In this part of the tutorial we'll just get our movies from a REST api by using Retrofit an awesome library by Square to work with REST apis.

Tools you need to start

Android Studio 1.3.0-beta1 or higher (Check out the Canary build)

Setting up the environments

  • Add following dependencies in your build.gradle file
dependencies {  
       classpath "com.android.tools.build:gradle:1.2.3"
       classpath "com.android.databinding:dataBinder:1.0-rc0"
}
  • Make sure jcenter() is in the repository list
allprojects {  
    repositories {
        jcenter()
    }
}
  • Add data binding plugin right after android plugin in each module's build.gradle you want to use data binding
apply plugin: 'com.android.application'  
apply plugin: 'com.android.databinding'  

Now start a new project named Movie List and apply the settings as mentioned above. We'll go through a simple project which will show a simple list of upcoming movies with a poster, name and year of release for each movie. We'll also build a detail view which will show the detail view for each of the moview with extra plot summery and casting. The mockup for the app will be like this,

Final Output

Let's take a quick look of the steps we're going to do along the way to develop the app,

  • We'll fetch upcoming movie data using an API from http://www.myapifilms.com and we'll use Retrofit library from Square to do that for us.
  • We'll develop a view that'll host our RecyclerView (Yes, we'll use RecyclerView not ListView)
  • We'll develop a view which will represent our each movie item and offcourse we'll use data binding.
  • Develop an adapter which can work with our data binding strategy.
  • Finally we'll add some UX like a loading indicator while we're fetching movie list and that'll also be taken care of by data binding.

Step 1:
Let's add Retrofit library in the dependency of the app module

compile 'com.squareup.retrofit:retrofit:1.9.0'  

Now let's create a package named rest(REST) and create an interface called MovieService. This interface will hold our API declaration to work with Retrofit library. Basically it's just mimicking our REST api. Now put the following code into this file,

public interface MovieService {  
    @GET("/comingSoon")
    public void getComingSoonMovies(Callback<List<MoviesByDate>> movies);
}

I've omitted the import statements for bravity.
Here we've just created a method signature which gives us a list of movies in the Callback provided by Retrofit. If you look at the @GET annotation you'll see the name of the api we'll use later. GET is the HTTP request type the API respond to. It's a get request. Similarly thare's other request types too.

Now go to your main activity of the application and add the following method,

private void fetchComingSoonMovies() {  
        RestAdapter restAdapter = 
                    new RestAdapter.Builder()
                    .setEndpoint("http://www.myapifilms.com/imdb").build();

        MovieService movieService = restAdapter.create(MovieService.class);
        movieService.getComingSoonMovies(new Callback<List<MoviesByDate>>() {
            @Override
            public void success(List<MoviesByDate> moviesByDates, Response response) {

            }

            @Override
            public void failure(RetrofitError error) {
                Toast.makeText(getApplicationContext(), 
                               "Unexpected error occured", 
                               Toast.LENGTH_LONG).show();
            }
        });
    }

Let's talk about what we've just done. We've created a RestAdapter which is a part of Retrofit library and added the endpoint of the API we'll use. Then we've used the create method of RestAdapter with our previously created MovieService class to get a concrete implementation. Here we're using '/comingSoon' API so, Retrofit will call the API with provided end point. To be clear the whole API will be http://www.myapifilms.com/imdb/comingSoon. You've probably found out already that all the successive API you want to use with same end point will go to the MovieService class.

At this point you'll see some error because we didn't create the MovieByDate model class. Lets create another package with the name models and create a class named MovieByDate.

Now let's take a look at the response of our API,

[
    {
        "date": "July 3 ",
        "movies": [
            {
                ...
                "title": "Terminator Genisys",
                ...
                "urlPoster": "http://ia.media-imdb.com/images/M/MV5BMjM1NTc0NzE4OF5BMl5BanBnXkFtZTgwNDkyNjQ1NTE@._V1_SX214_AL_.jpg",
                ...
                "year": "2015"
            },
            ...
        ]
    },
    ...
]

This API return an array of object which contains another array of movies and those objects are group by date (Look at the above response or hit the URL in the browser). We're interested into the array of movies of every object. We're specifically interested to the title, year and poster url of each movie (I've omitted extra responses for bravity). So, if we create a simple class and map the json properties to the class we get the following code,

public class MoviesByDate {  
    private String date;
    private List<Movie> movies;

    public List<Movie> getMovies() {
        return movies;
    }
}

Now we get another error and that is beacuse we didn't create our Movie model. So let's create it in the model package.

public class Movie {  
    @SerializedName("urlPoster")
    private String poster;

    @SerializedName("title")
    private String title;

    @SerializedName("year")
    private String year;

    public void setPoster(String poster) {
        this.poster = poster;
    }

    public String getPoster() {
        return poster;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getYear() {
        return year;
    }
}

It's a POJO (Plain Old Java Object). Now you can see there is an extra annotation @SerializedName and they are the part of GSON library. Don't worry you don't have to add GSON in your dependency, it's comes with Retrofit by default. Now which this annotation is doing is mapping the JSON field's value to the appropriate property of your java object. So you don't have to parse the JSON, Retrofit will by default give you the parsed response.

Let's just summarize what we've done here so far. We've creates MovieByDate class to hold the structure of the object in the response array and we've added a list of movies to that class just to make it look like the JSON equivalent. Now we'll get
our list of movies from each MovieByDate object.

Now add the following permissions to your AndroidManifest.xml,

<uses-permission android:name="android.permission.INTERNET" />  

Now call the fetchComingSoonMovies() method from the onCreate and you'll get all your movies inside each of MovieByDate object in the List<MovieByDate> moviesByDates provided in the success callback of the MovieService.

It's the end of part 1 of this tutorial and I know this is not so interesting right now but you'll get amazed by the next part where you'll see the magic of data binding. Till then,

Happy coding.

comments powered by Disqus