首页 > 解决方案 > Android:通用改造 2

问题描述

我只尝试了 1 次创建改造但我有错误我想调用我的改造类并给出 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)

改造不支持通用对象???

标签: javaandroidgenericsretrofitretrofit2

解决方案


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

首先,您将使用以下内容封装改造设置:

@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根据抛出的异常获取适当的消息。


推荐阅读