For last year since I found about Kotlin I’m learning how to use it in Android app development, Spring framework etc. I’m still amazed how expressive and functional this programming language is compared to our old friend Java. Kotlin is constantly updated with new features and it’s getting better and more popular every day.
I’m using angular and other javascript frameworks like vue in my work. I just love how easy is to work with API data with angular’s HttpClient, rx observables and other great tools packed with it. With few lines of code you get so much done. Now with Kotlin, Retrofit and RXJava you can do almost same in android development. In this tutorial I’ll try to show you just few cool and useful possibilities.
In this tutorial we will make simple client app which will consume API data from JSONPlaceholder API.
We will start by creating new project in Android Studio, include Kotlin support and choose Empty Activity for start.
Setup
Add Retrofit and RXJava dependencies in build.gradle(Module:app) file and Sync.
implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
Add Internet permision in AndroidManifest.xml to get internet access.
<uses-permission android:name="android.permission.INTERNET"/>
API
Our project is now setup and ready now it’s time for some magic. As I said before this app will consume data from JSONPlaceholder API. We will use https://jsonplaceholder.typicode.com/posts endpoint to get list of articles. If you open this link in your browser you will get list articles as json objects.
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }, { "userId": 1, "id": 3, "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut", "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut" }, ...
Sending POST request to https://jsonplaceholder.typicode.com/posts with article in request body will add new article. If we pass article ID as path parameter we will get single article object in API response.
{ "userId": 2, "id": 11, "title": "et ea vero quia laudantium autem", "body": "delectus reiciendis molestiae occaecati non minima eveniet qui voluptatibus\naccusamus in eum beatae sit\nvel qui neque voluptates ut commodi qui incidunt\nut animi commodi" }
Article
We can use this response to define our Article class to which we will map our json objects from response.
Create new Kotlin file and define Article class.
data class Article( val userId: Int, val id: Int, val title: String, val body: String )
Article API Client
If you used Retrofit with Java before you know that we need to define interface where we will describe our HTTP requests, functions to trigger those requests and expected response types. In Kotlin it is similar but there is’t so much code and it’s really easy. In our ArticleApiClient interface we will define:
GET request for returning list of Articles
GET request to return Article by it’s id
POST request to add new Article
All requests will return Observables to which we will have to subscribe later by using RXJava . Create new Kotlin file and define ArticleApiClient interface:
package com.example.samir.apiclientapp import io.reactivex.Observable import retrofit2.Retrofit import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.* interface ArticlesApiClient { /* Get list of articles */ @GET("posts") fun getArticles(): Observable<List<Article>> /* Get one article by it's id */ @GET("posts/{id}") fun getArticle(@Path("id") id: Int): Observable<Article> /* Add new article */ @Headers("Content-Type: application/json;charset=utf-8") @POST("posts") fun addArticle(@Body article: Article): Observable<Article> companion object { fun create(): ArticlesApiClient { val retrofit = Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .baseUrl("https://jsonplaceholder.typicode.com/") .build() return retrofit.create(ArticlesApiClient::class.java) } } }
Most of this will be familiar to you if you used retrofit with Java except the companion object which is Kotlin’s feature. The companion object is a singleton object. The methods in the companion object are analogous to (public) static methods, it is an actual object instead of just a loose set of functions and fields within a specific scope. This allows interface implementation, assignment to variables, etc. In this case we will use it to define function which will return ArticlesApiClient instance.
Implementation
Our ArticleApiClient is ready and we can consume API data. To test our little client app we will add three functions in our MainActivity.kt file. Each function will use RXJava to subscribe to Observables and log response so we can see it in our Logcat output.
package com.example.samir.apiclientapp import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers class MainActivity : AppCompatActivity() { val client by lazy { ArticlesApiClient.create() } var disposable: Disposable? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Uncomment to show list of articles in Logcat //showArticles() // Uncomment to show article with id=1 in Logcat //showArticle(1) // Test post request and add new article val article = Article(1, 101, "Test Article", "Have fun posting") postArticle(article) } // GET List of Articles private fun showArticles() { disposable = client.getArticles() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { result -> Log.v("ARTICLES", "" + result) }, { error -> Log.e("ERROR", error.message) } ) } // GET Article by id private fun showArticle(id: Int) { disposable = client.getArticle(id) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { result -> Log.v("ARTICLE ID ${id}: ", "" + result) }, { error -> Log.e("ERROR", error.message) } ) } // POST new Article private fun postArticle(article: Article) { disposable = client.addArticle(article) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { result -> Log.v("POSTED ARTICLE", "" + article ) }, { error -> Log.e("ERROR", error.message ) } ) } override fun onPause() { super.onPause() disposable?.dispose() } }
Please check full app code on github https://github.com/SKaDiZZ/apiclient
Now when you have your data it’s easy to output it in RecyclerView or wherever you need it. I had limited free time to write this article but I hope you guys will find it useful in your work or learning. Kotlin is new amazing kid in neighborhood and you should use it.
Please check part 2 of this tutorial
Recommended reading
- Kotlin companion object documentation
- Kotlin Faster Lazy for Android by Juan Ignacio Saravia
- Kotlin by lazy documentation
- Understanding, creating and subscribing to observables in Angular by Luuk Gruijs
- RESTful Web Services Tutorial with Example by Alex Nordeen