使用Observable.from和flatMap对List中的每个项执行操作,并在每个列表元素

时间:2017-04-27 20:49:40

标签: android observable retrofit2 flatmap

我得到了一个searchItems列表。对于此列表中的每个元素,存在Lat und Lng。对于这些坐标,我使用googleService来获取这两个值,并返回一个名为(城市名称)的JsonObject。这很好用!在我的onNext中,我可以在我的日志输出中看到该城市。

现在我的问题:我想将此名称存储在相应的列表元素中。喜欢:item.setLocation(loc) - >但是我无法在onNext()中设置对项目的访问权限!我怎样才能访问项目?

 Observable.from(searchItems)
            .flatMap(item -> googleService.getCityNameFromLatLngObserable(item.getLat(), item.getLng(), null)
            .subscribeOn(Schedulers.io()))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<JsonObject>() {
                @Override
                public void onCompleted() {
                    view.updateSearches(searchItem);
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(JsonObject response) {
                    if (response.get("results").getAsJsonArray().size() > 0) {
                        String loc = response.get("results").getAsJsonArray()
                                .get(0).getAsJsonObject().get("address_components").getAsJsonArray()
                                .get(2).getAsJsonObject().get("long_name").toString();
                        Log.d("CONAN", "City: "+loc);

                        item.setLocation(loc); //does not work
                    }
                }
            });

1 个答案:

答案 0 :(得分:0)

实际上你不应该真正改变你的searchItems,而应该使用新信息创建新的zip。这是为了强制执行不变性,这对Rx来说非常珍贵。

有多种方法可以做到这一点,但这是一种可行的方法。您需要该项目才能调用您的Google服务,因此您无法使用Observable.from(searchItems) 或其任何朋友。所以,让我们保持第一位就像你拥有它并获得一个可观察的发射每个搜索项目:

Observable.from(searchItems)
          .flatMap(item -> googleService
                              .getCityNameFromLatLngObserable(
                                    item.getLat(),
                                    item.getLng(), null)
                              .map(jsonObject -> /* create a 
                                                    new item with location */))
          .subscribeOn(Schedulers.io()))
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(new Subscriber<JsonObject>() {
            @Override
            public void onCompleted() {
                view.updateSearches(searchItem);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Item item) {
                   // Your items with location
            }
        });

现在让我们继续创建包含其位置的新搜索项。

googleService. getCityNameFromLatLngObserable

我所做的是将createWithLocation(item, getLocation(jsonObject))的结果映射到具有结果位置的项目。请注意,如何通过google访问item和json对象?

现在在map函数中你可以使用item.toBuilder() .location(getLocation(jsonObject)) .build(); 之类的函数或使用类似构建器模式的函数:

onNext

另请注意,在订阅者Item上,您现在拥有JsonObject而不是getLocation并填充了该位置。我假设你可以编码{{1}},因为你的例子已经有了这个。

最后,您还可以在项目实例中调用setter而不是创建新的setter。我建议不要这样做,因为你会为其他人可能没想到的电话添加副作用。它通常是bug的来源。但是,您仍然可以这样做:)

希望有所帮助