如何使用RxJava更改对象列表

时间:2016-02-23 12:28:56

标签: android retrofit rx-java rx-android

我尝试使用StackOverFlow API。我希望标记列表包含名称,计数和描述。问题是描述以不同的api函数返回:

https://api.stackexchange.com/2.2/tags?page=1&pagesize=3&order=desc&sort=popular&site=stackoverflow

只给出了3个所需字段中的两个:(通过点击链接尝试:)

  • 1)姓名
  • 2)的计

https://api.stackexchange.com/2.2/tags/javascript%3Bjava%3Bc%23/wikis?site=stackoverflow 取标签名称并给我:

  • 3)摘录(介绍)

我构建了一个Retrofit界面:

 class Item {
    @SerializedName("name")
    public String name;
    @SerializedName("count")
    public String count;
    @SerializedName("excerpt")
    public String excerpt;
}

class Items {
    @SerializedName("items")
    public Item[] items;
}

@GET("/2.2/tags")
Observable<Items> getItems(@Query("page") String page,
                          @Query("pagesize") String pagesize,
                          @Query("order") String order,
                          @Query("sort") String sort,
                          @Query("site") String site);


@GET("/2.2/tags/{tagnames}/wikis")
Observable<Items> getDescription(@Path("tagnames") String tagnames,
                                        @Query("site") String site);

所以,首先,我们应该执行getItems,然后获取所有名称并执行getDescription func,最后使用新字段来填充我们的Items。 所以我想收集所有3个(一个可观察的名称,计数和摘录)。

到目前为止,这是我的观察者:

App.getServerAPI()
            .getItems("page", "pagesize", "order","sort", "site") //just example strings
            .observeOn(AndroidSchedulers.mainThread());

我应该怎么做?我应该在两个函数中使用Observable吗?

更新: 按照你的建议我到目前为止写了一个:

public Observable<ServerAPI.Tags> call() {
                        return App.getServerAPI()
                                .getItems("page", "pagesize", "order", "sort", "site")
                                .map(new Func1<ServerAPI.Tags, ServerAPI.Tags>() {
                                    @Override
                                    public ServerAPI.Tags call(ServerAPI.Tags tags) {
                                        String tagsStr = "";
                                        for (ServerAPI.Tag tag: tags.items){
                                            tagsStr +=tag.name+";";
                                        }
                                        ServerAPI.Excerts excerts = App.getServerAPI().
                                                getExcerts(tagsStr, "site");
                                        for (ServerAPI.Excert excertItem : excerts.items){
                                            for (ServerAPI.Tag tagItem: tags.items){
                                                if (excertItem.tag_name.equals(tagItem.name)){
                                                    tagItem.excerpt = excertItem.excerpt;
                                                }
                                            }
                                        }
                                        return tags;
                                    }
                                })
                                .delay(1, TimeUnit.SECONDS)
                                .observeOn(AndroidSchedulers.mainThread());

                    }

看起来很难看!

2 个答案:

答案 0 :(得分:1)

我会这样做:

Object

<强>更新

以下是为标签列表调用Api的示例。

class Tag{
    public String name;
    public String count;
}

class TagList {
    public List<Tag> tags;
}

class Excert {
    public String excert;
}

class Item {
    public final String name;
    public final String count;
    public final String excert;

    public Item(String name, String count, String excert) {
        this.name = name;
        this.count = count;
        this.excert = excert;
    }
}

Observable<TagList> getItems() {}

Observable<Excert> getExcert(String tagName) {}


public void testFlatMap() {
    getItems()
             //iterate over each Tag
            .flatMap(tagList -> Observable.from(tagList.tags))
             //call server for excert
            .flatMap(tag -> getExcert(tag.name),
                    new Func2<Tag, Excert, Item>() {
                        @Override
                        public Item call(Tag tag, Excert excert) {
                            //compose final data structure
                            return new Item(tag.name, tag.count, excert.excert);
                        }
                    })
            //item here
            .subscribe(item -> {

            });
}

答案 1 :(得分:0)

您可以更改getDescription方法:

Observable<Items> getDescription(@Path("tagnames") String tagnames,
                                        @Query("site") String site);

DescriptionResponse getDescription(@Path("tagnames") String tagnames,
                                        @Query("site") String site);

其中DescriptionResponse表示响应对象:

public class DescriptionResponse {
    List<DescriptionItem> items;
}

然后获取商品并使用map运算符获取说明并将其映射到您的商品:

api.getItems("", "", "", "", "").map(items -> {
    String tags = "";//iterate over items and grab all tags
    DescriptionResponse description = api.getDescription(tags, "");
    //iterate over items and descriptions in response and set appropriate description
    return items;
}).subscribe(items -> {
    //here is your items with descriptions
});