Android:通用改装2

时间:2018-12-05 09:48:53

标签: java android generics retrofit retrofit2

我只尝试了1次,但进行了改造,但我遇到了错误 我想打电话给我的改造类,并给url和body类提供endPoint,并清楚地从服务器获取主体

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 :(得分:0)

似乎您正在尝试通过调用泛型函数来最小化样板,但是有一种更好的方法可以做到这一点。

首先,您要用以下方法封装改造设置:

@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的函数,以基于引发的异常获取适当的消息。