Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Retrofit Design Patterns

I am using Retrofit to interact with my REST API, and was wondering whether anybody has any design suggestions.

My app has the following packages:

  1. models
  2. services
  3. activities
  4. fragments

The services package contains the interfaces for Retrofit. For example:

public interface FooService {
    @FormUrlEncoded
    @POST("foo/do")
    @Headers("Content-Type: application/x-www-form-urlencoded; charset=UTF-8")
    Call<FooBar> do();
}

Models contains...well, the different models. For example, FooBar. So far so good - just as per Retrofit documentation.

I have created an API class, that handles the Retrofit build logic (Retrofit retrofit = new Retrofit.Builder() etc), and exposes a static field: retrofit.In my activities I then can perform my requests as follows:

FooService service = API.retrofit.create(FooService.class);
Call<FooBar> call = service.do();

try {
    retrofit2.Response response = call.execute();
    // ...do stuff...
} catch(IOException) {}

And herewith comes my question: Would it be better to abstract the above further? So that I would not need to repeat the above everywhere? For example, something like:

MyOtherFooService service = new  MyOtherFooService();
FooBar fooBar = service.do();

Any thoughts? Recommendations?

like image 472
JB2 Avatar asked Apr 30 '16 21:04

JB2


People also ask

What design pattern does retrofit use?

Retrofit uses about 12 design patterns : 1- Builder Pattern: to separate the construction of a complex object from its representation.

Which design pattern is best for Android?

The singleton pattern ensures that only one object of a particular class is ever created. All further references to objects of the singleton class refer to the same underlying instance. There are very few applications, do not overuse this pattern. It's very easy to accomplish in Kotlin but not in java.

What is the retrofit in Android?

Retrofit is type-safe REST client for Android and Java which aims to make it easier to consume RESTful web services. We'll not go into the details of Retrofit 1. x versions and jump onto Retrofit 2 directly which has a lot of new features and a changed internal API compared to the previous versions.

What is Facade pattern in Android?

A facade, in the context of software design, is an object that provides a simplified interface to a larger body (or more complex) functionalities. This is useful especially when the client just need to simply call the interface in order to perform some tasks without having to know the implementation details of it.


2 Answers

I usually use singleton pattern with following structure :

first define ServiceHelper like following :

public class ServiceHelper {

private static final String ENDPOINT = "http://test.com";

private static OkHttpClient httpClient = new OkHttpClient();
private static ServiceHelper instance = new ServiceHelper();
private IPlusService service;


private ServiceHelper() {

    Retrofit retrofit = createAdapter().build();
    service = retrofit.create(IPlusService.class);
}

public static ServiceHelper getInstance() {
    return instance;
}

private Retrofit.Builder createAdapter() {

    httpClient.setReadTimeout(60, TimeUnit.SECONDS);
    httpClient.setConnectTimeout(60, TimeUnit.SECONDS);
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    httpClient.interceptors().add(interceptor);

    return new Retrofit.Builder()
            .baseUrl(ENDPOINT)
            .client(httpClient)
            .addConverterFactory(GsonConverterFactory.create());
}

public Call<List<CategoryModel>> getAllCategory() {
    return service.getAllCategory();
}

Then put all of your services in IService (in my case it's IPlusService)

    public interface IPlusService {
    //@Headers( "Content-Type: application/json" ) in Post method may use this
    @GET("/api/category")
    Call<List<CategoryModel>> getAllCategory();
}

Then call your singleton like below in your activity/fragment :

ServiceHelper.getInstance().getAllCategory().enqueue(new Callback<List<CategoryModel>>() {
        @Override
        public void onResponse(Response<List<CategoryModel>> response, Retrofit retrofit) {
            processResponse(response);
        }

        @Override
        public void onFailure(Throwable t) {
            processResponse(null);
        }
    });
like image 134
Amir Avatar answered Sep 27 '22 17:09

Amir


I would say don't do it. Especialy because most calls will need to use the async .enqueue and treat the error responses differently.

You could make your own abstract Retrofit Callback class and abstract the 'custom' callbacks from that so that you save yourself code duplication.

But generally I would like to see the app logic treating the response in the same place where I make the request.

Don't fall in the trap of overthinking it, or applying some abused pattern that doesn't really fit into Android.

And if your really need to pass that response along from your activity/fragment just use RxJava or even LocalBroadcast. Also try to read the Retrofit book.

like image 25
Radu Avatar answered Sep 27 '22 17:09

Radu