gpt4 book ai didi

java - 将 retrofit 回调值转换为返回封装对象

转载 作者:行者123 更新时间:2023-11-29 09:59:12 24 4
gpt4 key购买 nike

我的问题是关于使用 RxJava for Android 来操作来自 Retrofit 调用的数据的可能性。

我刚刚开始使用这些库,所以如果我的问题很简单,请耐心等待。

这是我的场景。

我有一个从服务器返回的 json,看起来像这样

  { <--- ObjectResponse
higher_level: {
data: [
{
...
some fields,
some inner object: {
....
},
other fields
}, <----- obj 1

....,

{
....
}<---- obj n

]<-- array of SingleObjects

}

} <--- whole ObjectResponse

我已经通过改造获得此响应并在 ObjectResponse 中进行了解析。解析这个对象,我可以获得一个列表,我可以像往常一样将它传递给我的 RecyclerView 适配器。

因此改造返回了 ObjectResponse,它是整个服务器响应的模型,在改造回调中,我操纵 ObjectResponse 来提取我的列表,然后将其传递给我的适配器。

现在,我有这样的东西

Call<ObjectResponse> call = apiInterface.getMyWholeObject();

call.enqueue(new Callback<ObjectResponse>() {
@Override
public void onResponse(Call<ObjectResponse> call, Response<ObjectResponse> response) {

//various manipulation based on response.body() that in the ends
// lead to a List<SingleObject>

mView.sendToAdapter(listSingleObject)
}

@Override
public void onFailure(Call<ObjectResponse> call,
Throwable t) {
t.printStackTrace();
}
});

我的问题是:

有没有一种方法可以从 retrofit 中获得一个 Observable,最终可以引导我发出 SingleObject 列表(并对其进行操作),而不必像我在 retrofit 回调中那样操作 ObjectResponse?或者我是否应该坚持使用改造回调,并且只有在获得列表之后我才能在将此列表提供给我的适配器之前使用 RxJava 进行操作?

我想得到这样的东西

        apiInterface
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<SingleObject>>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {

}

@Override
public void onNext(List<Post> posts) {

mView.sendToAdapter(listSingleObject)
}
});

最佳答案

改造转换器工厂很好地解决了这个问题。

Jake Wharton 在他的 "Making Retrofit Work For You" 中谈到“信封” 对象讨论并指出如何解决。

定义了一个信封类 - 一个包含一些您不关心的额外字段的类:

public class Envelope<T> {
Meta meta;
List<Notification> notifications;
T response;
}

在此 POJO 字段中 metaList<Notification>正在从后端返回,但在 android 应用程序的上下文中,我们对它们不感兴趣。假设,您需要从响应中获得的实际值是名为 response 的字段,它可以是任何对象(因为它是通用的)。

特别是在您的示例中,POJO 结构将如下所示:

public class OriginalResponse {
HigherLevel higher_level;
}

public class HigherLevel {
Data data;
}

public class Data {
List<ActualData> list;
}

您必须实现您的自定义 Converter.Factory :

public class EnvelopingConverter extends Converter.Factory {
@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
Type envelopedType = TypeToken.getParameterized(Envelope.class, type).getType();

Converter<ResponseBody, Envelope<?>> delegate = retrofit.nextResponseBodyConverter(this, envelopedType, annotations);
return body -> {
Envelope<?> envelope = delegate.convert(body);
// Here return the object that you actually are interested
// in your example it would be:
// originalResponse = delegate.convert(body);
// return originalResponse.higher_level.data.list;
return envelope.response;
};
}
}

将此转换器添加到您的改造构建器中:


new Retrofit.Builder()
...
.addConverterFactory(new EnvelopingConverter())
...

Then in your retrofit api interface instead of returning Single<OriginalResponse> return Single<List<ActualData>> directly:

interface Service {
@GET(...)
Single<List<ActualData>> getFoo();
}

Kotlin 中的典型实现:

class EnvelopeConverterFactory : Converter.Factory() {
override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
val envelopedType: Type = TypeToken.getParameterized(ParentObject::class.java, type).type

val delegate: Converter<ResponseBody, ParentObject> =
retrofit.nextResponseBodyConverter(this, envelopedType, annotations)

return Converter<ResponseBody, ChildObject> { body -> delegate.convert(body)?.childObject }
}
}

关于java - 将 retrofit 回调值转换为返回封装对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46884715/

24 4 0