Android: Generic Retrofit 2 - PullRequest
       15

Android: Generic Retrofit 2

0 голосов
/ 05 декабря 2018

я пробую это только один раз, чтобы создать модификацию, но у меня есть ошибка, я хочу вызвать мой класс модернизации и дать конечную точку URL-адреса и класса тела, а также получить тело с сервера ясно

ApiClient

public class ApiClient {
    private static Retrofit retrofit = null;
    public static Retrofit getClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(App.SERVER)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

ApiService

public interface ApiService {
    @POST("{urlEndPoint}")
    <C, T> Call<C> request(@Body T body, @Path("urlEndPoint") String urlEndPoint);
}

Модифицированный объект

public class Request<C,T> {
    private C c = null;
    public C rest(T body, String urlEndPoint) {
        ApiService apiService = ApiClient.getClient().create(ApiService.class);
        Call<C> call = apiService.request(body, urlEndPoint);
        call.enqueue(new Callback<C>() {
            @Override
            public void onResponse(Call<C> call, Response<C> response) {
                if (response.isSuccessful())
                    c = response.body();
                else
                    Toaster.shorter(App.context.getString(R.string.serverError));
            @Override
            public void onFailure(Call<C> call, Throwable t) {
                Toaster.shorter(App.context.getString(R.string.connectionError));
            }
        });
        return c;
    }
}

метод вызова:

private void requestForCode() {
    Request request = new Request();
    int i = (int) request.rest(App.car, "/Rest/ReturnActivationCode");
    if (i == 0)
        Toaster.longer(App.context.getString(R.string.validateYourNumber));
    else
        Toaster.shorter(App.context.getString(R.string.serverError));
}

ошибка:

12-05 12:18:04.119 773-907/? E/ConnectivityService: RemoteException caught trying to send a callback msg for NetworkRequest [ id=535, legacyType=-1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED] ]
12-05 12:18:09.575 10359-10359/com.rayanandisheh.peysepar E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.rayanandisheh.peysepar, PID: 10359
    java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call<C>
        for method ApiService.request
        at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:755)
        at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:746)
        at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:229)
        at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:165)
        at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
        at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
        at java.lang.reflect.Proxy.invoke(Proxy.java:393)
        at $Proxy0.request(Unknown Source)

дооснащение не поддерживает универсальные объекты ???

1 Ответ

0 голосов
/ 05 декабря 2018

Кажется, что вы пытаетесь свести к минимуму свой шаблон, используя для вызова общую функцию, но есть лучший способ сделать это.

Сначала вы инкапсулируете настройку модернизации с помощью:

@POST("{urlEndPoint}")
<C, T> Call<C> request(@Body T body, @Path("urlEndPoint") String urlEndPoint);

И затем вызываете ее с созданной вами функцией:

request.rest(App.object1, "endpoint");

Но на самом деле это только усложнит ситуацию, и код будет очень тесно связан.Вам все равно нужно будет вызывать один и тот же метод для всех различных API (request.rest(App.object2, "endpoint2"), request.rest(App.object3, "endpoint3")).Это также ограничивает возможности модификации (, например, несколько параметров, настройка заголовков и т. Д. ).Что вы можете сделать, это просто выполнить настройку дооснащения:

@POST("yourendpoint") Call<YourObjectResp> saveObject(@Body YourObjectParam param)

И чтобы свести к минимуму ваш шаблон, я предлагаю сделать его функциональным :

Call<YourObjectResp> call = apiService.saveObject(new YourObjectParam());
call.enqueue(new ApiServiceOperator<>(new 
   ApiServiceOperator.OnResponseListener<YourObjectResp>() {
            @Override
            public void onSuccess(YourObjectResp body) {
                // do something with your response object
            }

            @Override
            public void onFailure(Throwable t) {
                // here, you can create another java class to handle the exceptions
            }
        }));

А для вашего ApiServiceOperator.java:

/**
* Handles retrofit framework response.
* Extract the body if success, otherwise throw an exception.
*/
public class ApiServiceOperator<T> implements Callback<T> {

    interface OnResponseListener<T> {
        void onSuccess(T body);

        void onFailure(Throwable t);
    }

    private OnResponseListener<T> onResponseListener;

    public ApiServiceOperator(OnResponseListener<T> onResponseListener) {
        this.onResponseListener = onResponseListener;
    }

    @Override
    public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {
        if (response.isSuccessful()) { // here, do the extraction of body
            onResponseListener.onSuccess(response.body());
        } else {
            onResponseListener.onFailure(new ServerErrorException());
        }
    }

    @Override
    public void onFailure(@NonNull Call<T> call, @NonNull Throwable t) {
        onResponseListener.onFailure(new ConnectionErrorException());
    }

    // these exception can be on a separate classes.
    public static class ServerErrorException extends Exception {
    }

    public static class ConnectionErrorException extends Exception {
    }
}

С этими настройками вы по-прежнему минимизируете свой шаблон, а также он делает вещь многоразовой, масштабируемой и тестируемой.ApiServiceOperator также свободно соединяется с Android Context и вместо этого выдает простое исключение Java, в котором вы можете создать функцию, которая знает Android Context, чтобы получить соответствующую базу сообщений при выданном исключении.

...