首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将改造后的回调值转换为返回包络对象

将改造后的回调值转换为返回包络对象
EN

Stack Overflow用户
提问于 2017-10-23 08:15:24
回答 2查看 4.1K关注 0票数 1

我的问题是,是否可能使用RxJava对安卓系统进行重新配置调用中的数据操作。

我刚刚开始使用这些库,所以如果我的问题是微不足道的,请耐心等待。

这是我的场景。

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

代码语言:javascript
复制
  { <--- ObjectResponse
     higher_level: {
        data: [
            {
               ...
               some fields,
               some inner object: {
               ....
                },
               other fields
            }, <----- obj 1

            ....,

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

         ]<-- array of SingleObjects

      }

  } <--- whole ObjectResponse

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

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

现在,我有这样的事情

代码语言:javascript
复制
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();
            }
         });

我的问题是:

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

我想买这样的东西

代码语言:javascript
复制
        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)
                }
            });
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-01 15:06:27

几天后,我可以发布我自己的解决方案。

它的灵感来源于azizbekian提出的想法。

中心思想是关于Envelope类的,我已经用retrofit注释来表达它,以确保它能够适应来自服务器的不同的JSON响应,解析

代码语言:javascript
复制
higher_level: {
        data: [
                mid_level: {  .. },
                ...
              ]
}

结构,我在最初的文章中已经解释过了。

代码语言:javascript
复制
public class WrapperResponse<T> {
    @SerializedName(value="higher_level", alternate={"mid_level", "other"})
    @Expose
    DataResponse<T> data;

    public DataResponse<T> getData() {
        return data;
    }

    public void setData(DataResponse<T> data) {
        this.data = data;
    }
}

这里的重点是SerializedName的参数,其中我指定了服务器响应中出现的所有可能的JSON对象名称。

那我就有

代码语言:javascript
复制
public class UnwrapConverterFactory extends Converter.Factory {

    private GsonConverterFactory factory;

    public UnwrapConverterFactory(GsonConverterFactory factory) {
        this.factory = factory;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(final Type type,
                                                            Annotation[] annotations, Retrofit retrofit) {
        Type wrappedType = new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                return new Type[] {type};
            }

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

            @Override
            public Type getRawType() {
                return WrapperResponse.class;
            }
        };
        Converter<ResponseBody, ?> gsonConverter = factory
                .responseBodyConverter(wrappedType, annotations, retrofit);
        return new WrapperResponseBodyConverter(gsonConverter);
    }
}

代码语言:javascript
复制
public class WrapperResponseBodyConverter<T>
        implements Converter<ResponseBody, T> {
    private Converter<ResponseBody, WrapperResponse<T>> converter;

    public WrapperResponseBodyConverter(Converter<ResponseBody,
            WrapperResponse<T>> converter) {
        this.converter = converter;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
        WrapperResponse<T> response = converter.convert(value);

            return response.getData().getData();

    }
}

在我的重装模块(dagger2)中使用,以确保我的重装客户端使用通用WrapperResponse打开来自服务器的任何答案,最后,我可以将Retrofit方法写成

代码语言:javascript
复制
@GET("locations")
Observable<List<Location>> getLocation();

这里的列表正是我想要得到的结果:一个直接来自Retrofit响应的对象列表,我可以用RxJava进一步详细说明。

谢谢大家。

票数 1
EN

Stack Overflow用户

发布于 2017-10-23 08:39:14

据我所知,没有办法。对于最佳实践,您应该创建一个Facade层(可能是一个ApiManager类)来管理您的所有API。在这种情况下,可以使用map/flatMapObjectResponse映射到SingleObject,如下所示:

代码语言:javascript
复制
public Observable<List<SingleObject>> getSingleObjects(){
    return ServiceGenerator.getApiMethods().getObjectResponse.map(new Function<ObjectResponse, List<SingleObject>>() {
        @Override
        public List<SingleObject> apply(ObjectResponse response) throws Exception {
            return reponse.getListSingleObjects();
        }
    })
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46884715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档