ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Unsplash @ kalkie

Handling network HTTP response of success data and failure for your Android project using Sandwich.

Jaewoong Eum
ProAndroidDev
Published in
4 min readMay 8, 2020

Requesting data to remote server and handling responses is always one of the important issues in Android development. When we are building our project even a small-sized demo project, we have to spend time constructing the REST service structure. Using the modern Android development tool like Retrofit2, OkHttp, LiveData, or RxJava we can implement the network interfaces easily and request asynchronously. But designing standardized response models/interfaces and handling success data and errors are also important things.

In this post, we’re going to find about how to build a network structure and handle success, failure data from the responses using the Sandwich library.

Including

We should import the dependency of the library to our build.gradle file.

dependencies {
implementation "com.github.skydoves:sandwich:1.0.1"
}

ApiResponse

ApiResponse is an interface of the retrofit response for handling data and error response with useful transformation extensions. We can get ApiResponse using the scope extension request from the Call.
Let’s see how to get and use the ApiResponse from the DisneyService.

After getting an instance of the disneyService from the retrofit.create, we can call the the fetchDisneyPosterList().reqeust. The reqeust method receives a lambda function and we can get an instance of theApiResponse via reqeust lambda. There are three types of ApiResponse.

ApiResponse.Success

API success response class from the Retrofit service.
We can get the response body data, StatusCode, Headers and etc from the ApiResponse.Success. If we received 2xx status code from the remote server, we can get the data from the ApiResponse.Success.

ApiResponse.Failure.Error

API format does not match or applications need to handle errors.
e.g. Internal server error (4xx, 5xx server error).

ApiResponse.Failure.Exception

An unexpected exception occurs while creating the request, processing the response, or parsing error in the client. The problem is the client, so we can’t get an error body or status code. Instead, we can get an exception.
e.g. Network connection error.

ApiResponse Extensions

We can handle response cases more handy using extensions using onSuccess, onError, onException. We can use these scope functions to the ApiResponse, it reduces the usage of the if/when clause.

ApiErrorModelMapper

Sometimes we have to get our own error response model from the error response. We can map ApiResponse.Failure.Error model to our customized error model using the mapper. Below example shows how to transform ApiResponse.Failure.Error to ErrorEnvelope via ErrorEnvelopeMapper.

ResponseDataSource

ResponseDataSource is an implementation of the DataSource interface. We can bind an instance of the Call to the ResponseDataSource. The ResponseDataSource requests asynchronously, and it holds data if the response success. we can observe every response. Also, we can retry fetching data (re-request) if our request got failure.

  • Asynchronously send requests.
  • A response data holder from the REST API call for caching data on memory.
  • Observable for every response.
  • Retry fetching data when the request gets failure.
  • Concat another DataSource and request sequentially.

Combine

Combine a Call and lambda scope for constructing the DataSource.

Request

Request API network call asynchronously.
If the request is successful, this data source will hold the success response model. In the next request after the success, request() returns the cached API response. If we need to fetch a new response data or refresh, we can use invalidate().

dataSource.request()

Retry

Retry requesting API call when the request gets failure.

ObserveResponse

Observes every response data ApiResponse from the API call request.

dataSource.observeResponse {
Timber.d("observeResponse: $it")
}

Invalidate

Invalidate a cached (holding) data and re-fetching the API request.

dataSource.invalidate()

Concat

Concat an another DataSource and request API call sequentially if the API call getting successful.

Here is the example of the ResponseDataSource in the MainViewModel.

DataSourceCallAdapterFactory

We can get the DataSource directly from the Retrofit service.
Add a call adapter factory DataSourceCallAdapterFactory to your Retrofit builder. And change the return type of your service Call to DataSource

Here is the example of the DataSource in the MainViewModel.

Handle your network responses more structurally

We looked around into how to build a network structure and handle success, failure data from the responses using the Sandwich library. If you want to get more information about the Sandwich library, you can check the GitHub link :) Thank you!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Jaewoong Eum

Senior Developer Advocate @ RevenueCat 🥑 • GDE for Android • OSS engineer. Love psychology, magic tricks, and writing poems. https://github.com/skydoves

Responses (1)

Write a response