Retrofit library
Retrofit is a type-safe REST client for Java and Android. It requires at minimum Java 8+ or Android API 21+.
Annotations are used to describe the HTTP request:
- URL parameter replacement and query parameter support
- object conversion to request body (e.g., JSON, protocol buffers)
- multipart request body and file upload
Library page on GitHub. Official doc is here.
Add dependency
implementation("com.squareup.retrofit2:retrofit:2.9.0")
1. First define interface of REST service.
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
@POST("users/new")
Call<User> createUser(@Body User user);
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first,
@Field("last_name") String last);
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo,
@Part("description") RequestBody description);
// ...
}
2. Generate an implementation of the interface.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
3. Create Call objects to perform synchronous or asynchronous HTTP requests to the remote webserver.
Call<List<Repo>> repos = service.listRepos("octocat");
// synchronous
Response response = repos.execute();
// asynchronous
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call,
Response<List<Repo>> response) {
// request is success, but check response.body() on null
// ...
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
// error
}
});
convertes
Retrofit provides different converters to (de)serialize the data. To do this, add the following dependency:
- Gson: com.squareup.retrofit2:converter-gson
- Jackson: com.squareup.retrofit2:converter-jackson
- Moshi: com.squareup.retrofit2:converter-moshi
- Protobuf: com.squareup.retrofit2:converter-protobuf
- Wire: com.squareup.retrofit2:converter-wire
- Simple XML: com.squareup.retrofit2:converter-simplexml
- JAXB: com.squareup.retrofit2:converter-jaxb
- Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
// Gson allows to convert json response
// to the java object
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService gitHubService = retrofit.create(GitHubService.class);
adapters
Retrofit ships with a default adapter for executing Call instances. But you can use other popular execution mechanisms like RxJava, Guava, Java 8 (see additional retrofit adapters on github).
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com")
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
retrofit with coroutines
Recent versions of Retrofit support Kotlin coroutines. Just add suspend keyword to the inteface functions.
You can also wrap the result type with a Response class to execute request in current context.
interface GitHubService {
@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String): Response<List<Repo>>
}
class MyViewModel: ViewModel() {
// ...
val userName: String
val repoList = MutableLiveData<List<Repo>>>()
val isRepoLoading = MutableLiveData<Boolean>()
val errorMessage = MutableLiveData<String>()
// ...
fun loadRepo() {
viewModelScope.launch {
val response = gitHubService.listRepos(userName)
withContext(Dispatchers.Main) { // switch to main thread
if (response.isSuccessful) { // if ok set new values
repoList.postValue(response.body())
loading.value = false
} else {
onError("Error : ${response.message()} ")
}
}
}
}
private fun onError(message: String) {
errorMessage.value = message
loading.value = false
}
}