当前位置: 首页 > 知识库问答 >
问题:

自定义呼叫适配器改型中的泛型类型

凌宏大
2023-03-14

改型异步请求是用两个方法onResponse()和onFailure()回调的。

public class ApiResponse<T> {

    public final int code;
    @Nullable
    public final T body;
    @Nullable
    public final String errorMessage;

    public ApiResponse(Throwable error) {
        code = -1;
        body = null;
        if (error instanceof IOException) {
            errorMessage = "No network error";
        }
        else {
            errorMessage = error.getMessage();
        }
    }

    public ApiResponse(Response<T> response) {
        code = response.code();
        if (response.isSuccessful()) {
            body = response.body();
            errorMessage = null;
        }
        else {
            String message = null;
            if (response.errorBody() != null) {
                try {
                    message = response.errorBody().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (message == null || message.trim().length() == 0) {
                message = response.message();
            }
            errorMessage = message;
            body = null;
        }
    }

    public boolean isSuccessful() {
        return code >= 200 && code < 300;
    }
}

我还想使用Gson转换器来转换改型响应,然后用APIPesponse包装它。

如果我用like

Call<ApiResponse<Result>> requestCall = webClient.request1(xxx,xxx);
requestCall.enqueue(new Callback<ApiResponse<Result>> {});

好像不起作用。不能将json响应数据解析到结果对象中。

public class MyCallAdapterFactory extends CallAdapter.Factory {
    @Nullable
    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

        if (getRawType(returnType) != MyCall.class) {
            return null;
        }

        Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
        Class<?> rawObservableType = getRawType(observableType);
        if (rawObservableType != ApiResponse.class) {
            throw new IllegalArgumentException("type must be a resource");
        }
        if (! (observableType instanceof ParameterizedType)) {
            throw new IllegalArgumentException("resource must be parameterized");
        }
        Type bodyType = getParameterUpperBound(0, (ParameterizedType) observableType);
        Executor executor = retrofit.callbackExecutor();
        return new MyCallAdapter<>(bodyType, executor);
    }
}

public class MyCallAdapter<T> implements CallAdapter<T, MyCall<T>> {

    private final Type responseType;
    private final Executor callbackExecutor;

    public MyCallAdapter(Type responseType, Executor callbackExecutor) {
        this.responseType = responseType;
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public Type responseType() {
        return null;
    }

    @Override
    public MyCall<T> adapt(Call<T> call) {
        return new MyCallImpl<>(call, callbackExecutor);
    }
}

public class MyCallImpl<T> implements MyCall<T> {
    private final Call<T> call;

    private final Executor callbackExecutor;

    MyCallImpl(Call<T> call, Executor callbackExecutor) {
        this.call = call;
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public void enqueue(MyCallback<T> callback) {
        call.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, Response<T> response) {
                /* This is the problem. it will seems wrap to ApiResponse<ApiResponse<Result>>> because T is <ApiResponse<Result>>.
                */
                callback.onResult(new ApiResponse<>(response));
            }

            @Override
            public void onFailure(Call<T> call, Throwable t) {
                /** This one is also the issue. */
                callback.onResult(new ApiResponse<>(t));
            }
        });
    }

    @Override
    public void cancel() {
        call.cancel();
    }

    @Override
    public MyCall<T> clone() {
        return new MyCallImpl<>(call.clone(), callbackExecutor);
    }
}


public interface MyCallback<T> {

    void onResult(ApiResponse<T> response);

}
  Caused by: java.lang.NullPointerException: type == null
      at retrofit2.Utils.checkNotNull(Utils.java:286)
      at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:324)
      at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:313)
      at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:736)
      at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:169) 

有人能帮助如何让mycall > mycallback > 调用enqueue吗?结果是使用Gson转换器解析json数据内容。

public class MyCallAdapter<T> implements CallAdapter<T, MyCall<ApiResponse<T>>> {

   public MyCall<ApiResponse<T>> adapt(Call<T> call) {
        /* This one will have the problem after changing MyCall<T> to MyCall<ApiResponse<T>>, Parameterized type mismatch.*/
        return new MyCallImpl<>(call, callbackExecutor);
    }
}

有人能帮我指出这个问题吗?

共有1个答案

颛孙英勋
2023-03-14

修改MyCallAdapter、MyCallback和MyCalliMPL。@Rahul点出响应类型,现在一切工作都很好。

public class MyCallAdapter<T> implements CallAdapter<T, MyCall<ApiResponse<T>>> {

    private final Type responseType;
    private final Executor callbackExecutor;

    public MyCallAdapter(Type responseType, Executor callbackExecutor) {
        this.responseType = responseType;
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public MyCall<ApiResponse<T>> adapt(Call<T> call) {
        return new MyCallImpl<>(call, callbackExecutor);
    }
}


    public interface MyCallback<T> {

        void onResult(T response);

    }


public class MyCallImpl<T> implements MyCall<ApiResponse<T>> {
    private final Call<T> call;

    private final Executor callbackExecutor;

    MyCallImpl(Call<T> call, Executor callbackExecutor) {
        this.call = call;
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public void enqueue(MyCallback<ApiResponse<T>> callback) {
        call.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, Response<T> response) {
                callback.onResult(new ApiResponse<>(response));
            }

            @Override
            public void onFailure(Call<T> call, Throwable t) {
                callback.onResult(new ApiResponse<>(t));
            }
        });
    }

    @Override
    public void cancel() {
        call.cancel();
    }

    @Override
    public MyCall<ApiResponse<T>> clone() {
        return new MyCallImpl<>(call.clone(), callbackExecutor);
    }
}

以上是正确的实现。是啊。

 类似资料:
  • 主要内容:创建自定义适配器,注册自定义适配器,使用适配器Gson使用其内置适配器执行对象的序列化/反序列化。 它也支持自定义适配器。 让我们来讨论如何创建一个自定义适配器以及如何使用它。 创建自定义适配器 通过扩展类并传递目标类型的对象来创建自定义适配器。 重写读写方法分别执行自定义的反序列化和序列化。 注册自定义适配器 使用注册自定义适配器并使用创建一个Gson实例。参考以下实现代码 - 使用适配器 Gson现在将使用自定义适配器将Json文本转换为

  • 英文原文:http://emberjs.com/guides/models/customizing-adapters/ 在Ember Data中,处理与后台数据仓库通信的逻辑是通过Adapter来完成的。Ember Data适配器内置了一些关于REST API的假定。如果后台的实现与Ember Data假定的惯例不同,那么通过扩展缺省的适配器可能很容易的实现。 有时因为一些原因需要自定义适配器,例

  • Gson使用其内置适配器执行对象的序列化/反序列化。 它还支持自定义适配器。 我们将讨论如何创建自定义适配器以及如何使用它。 创建自定义适配器 通过扩展TypeAdapter类并将其传递给目标对象的类型来创建自定义适配器。 重写read和write方法以分别执行自定义反序列化和序列化。 class StudentAdapter extends TypeAdapter<Student> {

  • 问题内容: 下面的示例显示了一个类(Club),其中包含抽象类(成员)的集合。我对于是否需要TypeAdapter或JsonDeserializer才能使反序列化正常工作感到困惑。序列化在没有任何帮助的情况下就可以正常工作,但是反序列化会引发异常。为了说明这一点,我构建了以下“克隆”测试。如果有人能展示一个有效的例子,我将不胜感激。 头等舱 现在是抽象基类成员 以及成员的两个具体子类(金和银​​)

  • 如何将此迭代器与泛型类型一起使用?以下是我在“main”函数中尝试的方法: 结果是:<代码>无法从静态上下文引用非静态类项 结果是:<代码>无法从静态上下文引用非静态类项 结果: 编辑: 我调用的是类而不是方法。这项工作: 迭代器it=deq。迭代器(); 我认为,由于iterator()中返回的实例的类型是ListIterator,因此我需要使用该类型声明“it”。

  • 我想通过一个自定义的泛型unapply函数压缩我的计算器,该函数计算参数并在成功时返回值。 但是这失败了,错误 有什么方法可以实现这一点吗?我已经研究了类型标签,不适用方法的隐式转换,但我不知道如何将它们集成到这个问题中。如何正确定义Eval?