Retrofit2 MVP Android - PullRequest
       32

Retrofit2 MVP Android

0 голосов
/ 30 августа 2018

Я использую модификацию в своем проекте, и мне интересно, есть ли способ разделить вызовы API для другого класса, например: Войти Только активность / api / users / login Фильмы Активность только / API / фильмы / все У меня все в одном интерфейсе, и я вижу, что это не очень хороший подход ... не могли бы вы подсказать мне, как сделать его чище, пожалуйста? Я использую архитектуру MVP, чтобы сделать это чисто.

Это мой NetworkService.class

public class NetworkService {

    private NetworkAPI networkAPI;
    private OkHttpClient okHttpClient;
    private LruCache<Class<?>, Observable<?>> apiObservables;

    public NetworkService() {
        this(BASE_URL);
    }

    public NetworkService(String baseUrl) {
        okHttpClient = buildClient();
        apiObservables = new LruCache<>(10);

        Gson gson = new GsonBuilder()
                .setLenient()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        // set your desired log level
        //logging.setLevel(Level.BASIC);
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        Builder httpClient = new Builder()
                .connectTimeout(100, TimeUnit.SECONDS)
                .readTimeout(100, TimeUnit.SECONDS);

        httpClient.addInterceptor(logging);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(httpClient.build())
                .build();

        networkAPI = retrofit.create(NetworkAPI.class);
    }

    /**
     * Method to return the API interface.
     *
     * @return
     */
    public NetworkAPI getAPI() {
        return networkAPI;
    }


    /**
     * Method to build and return an OkHttpClient so we can set/get
     * headers quickly and efficiently.
     *
     * @return
     */
    public OkHttpClient buildClient() {

        Builder builder = new Builder();

        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Response response = chain.proceed(chain.request());
                // Do anything with response here
                //if we want to grab a specific cookie or something..
                return response;
            }
        });

        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                //this is where we will add whatever we want to our request headers.
                Request request = chain.request().newBuilder().addHeader("Accept", "application/json").build();
                return chain.proceed(request);
            }
        });

        return builder.build();
    }

    /**
     * Method to clear the entire cache of observables
     */
    public void clearCache() {
        apiObservables.evictAll();
    }
}

А у моего NetworkAPI.class есть

public interface NetworkAPI {


    @POST(LOGIN)
    Call<LoginResponse> login(@Body LoginRequest loginRequest);
    //And more calls...
}

Знаете ли вы, ребята, могу ли я сделать это чище?

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

Одна вещь, безусловно, должна быть оптимизирована, это то, что вы должны повторно использовать OkHttpClient вместо создания одного для API.

Создание модифицированного API также должно быть переработано как служебный класс:

public class RetrofitFactory {

    private static OkHttpClient baseClient = new Builder().addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            // Do anything with response here
            //if we want to grab a specific cookie or something..
            return response;
        }
    }).addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            //this is where we will add whatever we want to our request headers.
            Request request = chain.request().newBuilder().addHeader("Accept", "application/json").build();
            return chain.proceed(request);
        }
    }).build();

    private static Gson gson = new GsonBuilder()
            .setLenient()
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .create();

    private static Retrofit.Builder baseRetrofitBuilder = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson));


    public Builder baseClientBuilder() {
        return baseClient.newBuilder();
    }

    public static <T> T createApi(String url, Class<T> apiClass) {
        return baseRetrofitBuilder.baseUrl(url).build().create(apiClass);
    }

    public static <T> T createApi(String url, Class<T> apiClass, OkHttpClient client) {
        return baseRetrofitBuilder.baseUrl(url).client(client).build().create(apiClass);
    }
}

Чтобы создать NetworkAPI с дополнительным перехватчиком, вы должны сделать:

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    // set your desired log level
    //logging.setLevel(Level.BASIC);
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient httpClient = RetrofitFactory.baseClientBuilder()
            .connectTimeout(100, TimeUnit.SECONDS)
            .readTimeout(100, TimeUnit.SECONDS)
            .addInterceptor(logging);
    networkApi = RetrofitFactory.createApi(url, NetworkApi.class, httpClient);

Чтобы создать XApi с настройками по умолчанию, выполните:

    xApi = RetrofitFactory.createApi(url, XApi.class);
0 голосов
/ 30 августа 2018

Возможно, вы могли бы создать различные интерфейсы и изменить свой NetworkService для создания адаптера Retrofit в зависимости от интерфейса, который вы хотели бы использовать в разных случаях.

Позвольте мне показать вам идею:

Интерфейсы:

  public interface LoginInterface { 

        @POST(LOGIN) 
        Call<LoginResponse> login(@Body LoginRequest loginRequest); 
    }

    public interface MovieInterface {

        @GET(MOVIE) 
        Call<MovieResponse> getMovies(); 
    }

Класс NetworkService

Здесь вы можете увидеть Singleton for NetworkService и метод, созданный с помощью этого метода, вы можете создать различные интерфейсы, используя экземпляр singleton:

public class NetworkService {
    private final String API_BASE_URL = "";

    private static NetworkService INSTANCE = null;
    private static Retrofit retrofit;

    private OkHttpClient okHttpClient;
    private LruCache<Class<?>, Observable<?>> apiObservables;


    public NetworkService() {
        createInstance();
    }

    public static NetworkService getInstance() {

        if(INSTANCE == null){
            return new NetworkService();
        }

        return INSTANCE;
    }

    private void createInstance(){
        okHttpClient = buildClient();
        apiObservables = new LruCache<>(10);

        Gson gson = new GsonBuilder()
                .setLenient()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        retrofit = new Retrofit.Builder()
                .baseUrl(API_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(httpClient.build())
                .build();


        }

    public static <T> T create(Class<T> apiClass) {
        return retrofit.create(apiClass);
    }

    private OkHttpClient buildClient() {

        HttpLoggingInterceptor loggingInterceptor = new     HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addInterceptor(loggingInterceptor)
                .connectTimeout(100, TimeUnit.SECONDS)
                .readTimeout(100, TimeUnit.SECONDS);

        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Response response = chain.proceed(chain.request());
                // Do anything with response here
                //if we want to grab a specific cookie or something..
                return response;
            }
        });

        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                //this is where we will add whatever we want to our request headers.
                Request request = chain.request().newBuilder().addHeader("Accept", "application/json").build();
                return chain.proceed(request);
            }
        });


        return builder.build();
    }

    /**
     * Method to clear the entire cache of observables
     */
    public void clearCache() {
        apiObservables.evictAll();
    }
}

И затем вы можете использовать его экземпляр, используя ваш измененный NetworService, чтобы создать экземпляр интерфейса, который вы хотите использовать:

Создание экземпляра NetworService:

public class LoginActiviy extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);

            //Instantiation of LoginInterface
            LoginInterface loginInterface = 
            NetworkService.getInstance().create(LoginInterface.class);
            //Then we use the method for login
            loginInterface.login(/* Handling the callback here*/);

            }
        }

public class MoviesActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_movies);

            //Instantiation of MovieInterface
            MovieInterface movieInterface = 
            NetworkService.getInstance().create(MovieInterface.class);
            //Then we use the method for login
            loginInterface.getMovies(/* Handling the callback here*/);

            }
        }

Надеюсь, это поможет вам лучше понять.

0 голосов
/ 30 августа 2018

Создайте retrofit экземпляр синглтона, затем вы можете создавать сервисы для фильмов для входа, например

   LoginService login =  retrofit.create(LoginService.class);
   login.login(loginRequest)

   MovieService movie =  retrofit.create(MovieService.class);
   movie.movies(movieRequest)

Вот ваш интерфейс выглядит как

public interface LoginService {


    @POST(LOGIN)
    Call<LoginResponse> login(@Body LoginRequest loginRequest);
    //And more calls...
}

public interface MovieService {


    @POST(MOVIE)
    Call<MovieResponse> movies(@Body MovieRequest movieRequest);
    //And more calls...
}
...