Kotlin : Retrofit + RxAndroid + Realm

In this article I thought I should cover some of the libraries (that I use regularly), like Retrofit and Realm in the context of Kotlin and Rx.

If you’re new to Retrofit… Then I suggest you visit this article — and things will (hopefully) be crystal clear! And if you’re new to Rx & Kotlin — go here!

So let’s begin : Kotlin + Rx + Retrofit + Realm

If you’re anything like me, then you absolutely hate writing unnecessary code. *cough Java 6 cough*. And in my Android development experience, I’ve come across many situations where I was like

“But… Why?!”

In the context of Languages, I think Kotlin is definitely a life-saver. And libraries like Retrofit, Realm and RxAndroid also significantly reduce the amount of unnecessary code.

Simple Example: Getting data from Github API

For just this example I’d be using the same model for both database and API, in practice it’s not a good idea.

Keep your database schema and API models separate/independent.

So let’s begin.

Imagine an app which gets data from an API, stores/persists that data to the database and also displays it. A pretty common scenario, right?

This is what I’d be making… An extremely simple example… Which should hopefully cover the basics!

Nothing fancy — Just plain old me and my github info!

Creating the Project and Enabling Kotlin

The first thing we do is enable Kotlin in the project — Just make sure the Kotlin Plugin is installed in your Android Studio.

I created an Empty project with a single MainActivity — Went straight into the build.gradle file and… Triggered the action…

Trigger Action and search for Configure Kotlin
Select the modules and click OK
After clicking OK — this gets added to the build file — *Sync Changes*

Cool! Now we can write code in Kotlin!

MainActivity.java at the moment — Pretty standard stuff

We can (magically) convert the existing java code to Kotlin… By doing the following…

Action: Convert Java File to Kotlin File

Bamm! The MainActivity becomes…

Holy mother of Kotlin!

Adding Rx — Retrofit — Realm Dependencies

Time to add some dependencies!

I also use Databinding! Because cool people use Databinding!

Now you might be thinking what the hell is kapt?

Well it’s an annotation processor built for Kotlin.

sudo add this to build.gradle

In our project we’ll also have to enable generateStubs as well, in order for kapt to generate code.

So… Now we have everything we need! Time to start coding!

The Model

The endpoint we’re dealing with…

https://api.github.com/users/ahmedrizwan

And the response…

{
"login": "ahmedrizwan",
"id": 4357275,
"avatar_url": "https://avatars.githubusercontent.com/u/4357275?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/ahmedrizwan",
"html_url": "https://github.com/ahmedrizwan",
"followers_url": "https://api.github.com/users/ahmedrizwan/followers",
"following_url": "https://api.github.com/users/ahmedrizwan/following{/other_user}",
"gists_url": "https://api.github.com/users/ahmedrizwan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ahmedrizwan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ahmedrizwan/subscriptions",
"organizations_url": "https://api.github.com/users/ahmedrizwan/orgs",
"repos_url": "https://api.github.com/users/ahmedrizwan/repos",
"events_url": "https://api.github.com/users/ahmedrizwan/events{/privacy}",
"received_events_url": "https://api.github.com/users/ahmedrizwan/received_events",
"type": "User",
"site_admin": false,
"name": "ahmed",
"company": null,
"blog": null,
"location": "Rawalpindi, Pakistan",
"email": null,
"hireable": null,
"bio": null,
"public_repos": 9,
"public_gists": 0,
"followers": 5,
"following": 9,
"created_at": "2013-05-06T18:32:59Z",
"updated_at": "2015-08-29T18:17:58Z"
}

Ok for this example, I just want to extract id, name, avatar_url and public_repos from the response. So my model class (which is also a realm class btw), would look something like

*_*
Note: If you want to extract everything from the JSON response, then I suggest visiting to this awesome website, and generate a POJO. Then convert the Java code to Kotlin as described earlier.

Ok, lots of things to cover here… Starting off from the RealmClass annotation… For Realm, this annotation is necessary for Realm’s code generation in Kotlin… PrimaryKey annotation is also a Realm annotation, representing the Primary Key field (duh!)… Rest of the annotations are for Gson…

Now the open keyword! In kotlin it’s the opposite of final in Java. By default, Kotlin classes are final — that means if you want a class to be inherrited — we explicitly have to declare it as open. Same is the case with properties. Like in our model, name is a property, with an actual getter and a setter (thanks to Kotlin). And in order for the getter/setter to be overridable (which Realm requires them to be), we put the keyword open along with the declaration of the property. Which makes sense (to me at least).

Retrofit Interface

Again the endpoint url is

https://api.github.com/users/[some_user]

So the interface would look something like :-

Simplicity of Retrofit :’)

Notice how I’m returning Observable of a Github. This is possible because Retrofit allows Rx integration. And that’s super-super-cool!

Retrofit Builder

Yay… Now I can make API calls… ^_^

Because of Realm we use a special Gson instance, which basically adds an exclusion strategy for skipping Realm generated fields. Otherwise Gson doesn’t work with the model.

Next we create an instance of Retrofit with RxJavaCallAdapter factory which allows Rx integration and we also add the Gson converter using the Gson instance we created before.

Rx Magic

Lambdaaaaaaas! :’) Btw binding is my Databinding object!

Now all I do is get the observable, subscribe to it and get our Github object. Once we have the object, it’s easy to persist the user to Realm database.

Caching

Caching is also (sort of) possible, because we can first fetch data from Realm Database (if it has already been saved)… Like this…

Dayum!

And… That’s it! Now if you run the app…

*slow clap*

You can find the full code example here. Hope the article was somewhat useful!

Happy coding!