Calling API with Retrofit and Gson on Android
January 08, 2018
In this tutorial, we will create an Android application to call Github API using Retrofit and Gson.
Git Hub Project
The complete project can be cloned from here.
Prerequisites
- Please make sure Java and Android Studio IDE are installed on your system.
- We will be using Kotlin Language instead of Java. Please make sure Kotlin plugin is installed also.
Reference
- Excellent tutorials from CodePath.
Overview
Retrofit converts REST API call into a Java interface. Once we get the callable objects from Retrofit, we will convert those objects to/from JSON using Gson (which is to serialize and deserialize Java objects from/to JSON).
Briefly, our steps are
- Look at Github API and JSON response
- Convert JSON response into
class
that Gson can serialize/deserialize - Make Retrofit client with
GsonConverterFactory
- Define Github API routes
- Create service class to combine Retrofit client and Github API routes (which are defined in above two statements)
- Finally, make API calls in
MainActivity
to test the implementation.
Add Dependencies
In order to use Retrofit and Gson, we need these dependencies.
// Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
// JSON Parsing
compile 'com.google.code.gson:gson:2.8.2'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
Network Permisson
We need to network permission to call API.
<uses-permission android:name="android.permission.INTERNET" />
Convert GitHub User Json into Gson class
Now, we will be converting JSON response from GitHub API into something that Gson can serialize/ deserialize. You can look at how to get a single user from Github Doc.
At your browser, just type in the below statement. We are getting the username called octocat
which is used in GitHub Docs.
https://api.github.com/users/octocat
You should get the following JSON raw response
{
"login": "octocat",
"id": 583231,
"avatar_url": "https://avatars3.githubusercontent.com/u/583231?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false,
"name": "The Octocat",
"company": "GitHub",
"blog": "http://www.github.com/blog",
"location": "San Francisco",
"email": null,
"hireable": null,
"bio": null,
"public_repos": 7,
"public_gists": 8,
"followers": 2053,
"following": 5,
"created_at": "2011-01-25T18:44:36Z",
"updated_at": "2018-01-01T12:31:09Z"
}
We will use this website to convert JSON into class conveniently. So copy the JSON raw response above and paste it into the textbox. Select source type to JSON
and Annotation style to Gson
. Then click Preview
and copy the class as Java.
You should get the class with a long list of methods. Since we want to make 100% Kotlin, we will use Ctrl+Alt+Shift+K
key at Android Studio to convert Java class to Kotlin class that will result in the following class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package com.aknay.retrofit.model
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
class GitHubUser {
@SerializedName("login")
@Expose
var login: String? = null
@SerializedName("id")
@Expose
var id: Int? = null
@SerializedName("avatar_url")
@Expose
var avatarUrl: String? = null
@SerializedName("gravatar_id")
@Expose
var gravatarId: String? = null
@SerializedName("url")
@Expose
var url: String? = null
@SerializedName("html_url")
@Expose
var htmlUrl: String? = null
@SerializedName("followers_url")
@Expose
var followersUrl: String? = null
@SerializedName("following_url")
@Expose
var followingUrl: String? = null
@SerializedName("gists_url")
@Expose
var gistsUrl: String? = null
@SerializedName("starred_url")
@Expose
var starredUrl: String? = null
@SerializedName("subscriptions_url")
@Expose
var subscriptionsUrl: String? = null
@SerializedName("organizations_url")
@Expose
var organizationsUrl: String? = null
@SerializedName("repos_url")
@Expose
var reposUrl: String? = null
@SerializedName("events_url")
@Expose
var eventsUrl: String? = null
@SerializedName("received_events_url")
@Expose
var receivedEventsUrl: String? = null
@SerializedName("type")
@Expose
var type: String? = null
@SerializedName("site_admin")
@Expose
var siteAdmin: Boolean? = null
@SerializedName("name")
@Expose
var name: Any? = null
@SerializedName("company")
@Expose
var company: Any? = null
@SerializedName("blog")
@Expose
var blog: String? = null
@SerializedName("location")
@Expose
var location: Any? = null
@SerializedName("email")
@Expose
var email: Any? = null
@SerializedName("hireable")
@Expose
var hireable: Any? = null
@SerializedName("bio")
@Expose
var bio: Any? = null
@SerializedName("public_repos")
@Expose
var publicRepos: Int? = null
@SerializedName("public_gists")
@Expose
var publicGists: Int? = null
@SerializedName("followers")
@Expose
var followers: Int? = null
@SerializedName("following")
@Expose
var following: Int? = null
@SerializedName("created_at")
@Expose
var createdAt: String? = null
@SerializedName("updated_at")
@Expose
var updatedAt: String? = null
}
Retrofit Client
In order to call API and convert the response into Gson, we need a Retrofit client with Gson Converter. Therefore, we use Retrofit Builder
with GsonConverterFactory
for this class back.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.aknay.retrofit.retrofit
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClient {
private var mRetrofit: Retrofit? = null
private val BASE_URL = "https://api.github.com/"
val client: Retrofit
get() {
if (mRetrofit == null) {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
return mRetrofit!!
}
}
Define GitHub API Routes
Here, we are defining routes for Github API. Since we only want to get a single user, we will be converting GET /users/:username
API from Github Docs as this class.
1
2
3
4
5
6
7
8
9
10
11
12
package com.aknay.retrofit.retrofit
import com.aknay.retrofit.model.GitHubUser
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path
interface GitHubApiRoutes {
@GET("/users/{username}")
fun getUser(@Path("username") username: String): Call<GitHubUser>
}
GitHub User Service
After creating Retrofit Client and Routes, it is now time to combine these two and add into Service
class.
1
2
3
4
5
6
package com.aknay.retrofit.retrofit
object GitHubUserService {
val gitHubService: GitHubApiRoutes
get() = RetrofitClient.client.create(GitHubApiRoutes::class.java)
}
Main Activity
Now what’s left here is to call single user API call at MainActivity class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.aknay.retrofit
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.aknay.mRetrofit.R
import com.aknay.retrofit.model.GitHubUser
import com.aknay.retrofit.retrofit.GitHubApiRoutes
import com.aknay.retrofit.retrofit.GitHubUserService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
private var mGitHubApiRoutes: GitHubApiRoutes? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mGitHubApiRoutes = GitHubUserService.gitHubService
findViewById<Button>(R.id.button).setOnClickListener {
val userName = findViewById<EditText>(R.id.editText)!!.text.toString()
getUser(userName)
}
}
private fun getUser(userName: String) {
mGitHubApiRoutes!!.getUser(userName).enqueue(object : Callback<GitHubUser> {
override fun onResponse(call: Call<GitHubUser>, response: Response<GitHubUser>) {
if (response.isSuccessful) {
val msg = "Number of repo is : " + response.body()?.publicRepos
setTextView(msg)
} else {
setTextView("User may not exist")
}
}
override fun onFailure(call: Call<GitHubUser>, t: Throwable) {
setTextView("Fail to call")
}
})
}
private fun setTextView(text: String) {
findViewById<TextView>(R.id.textView)!!.text = text
}
}
Result
- Run with the emulator.
- Type in the username to get the number of Repo.
- If the user doesn’t exist, you will get
User may not exist
response.