使用 Observable.from 和 flatMap 对 List 中的每个项目执行操作并将结果设置在每个列表元素中
Using Observable.from and flatMap to perform operation on each item in an List and to set the result in each list element
我得到一个搜索项列表。此列表中的每个元素都存在一个纬度和经度。对于这些坐标,我使用采用这两个值的 googleService 和 returns 具有此位置名称(城市名称)的 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
}
}
});
实际上你不应该真的改变你的 searchItems
而是用新信息创建新的。这是为了加强不可变性,这对 Rx 来说非常重要。
有不止一种方法可以做到这一点,但这里有一种可能的方法。您需要该项目来调用您的 Google 服务,因此您不能使用 zip
或其任何朋友。因此,让我们像您拥有的那样保留第一位,并获得发出每个搜索项的可观察对象:
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
的结果映射到具有结果位置的项目。请注意,在这里您如何通过 google?
访问项目和 json 对象 return
现在在 map 函数中,您可以使用诸如 createWithLocation(item, getLocation(jsonObject))
之类的函数,也可以使用诸如构建器模式之类的函数:
item.toBuilder()
.location(getLocation(jsonObject))
.build();
另请注意,在订阅者 onNext
上,您现在有一个 Item
而不是 JsonObject
并且位置已填充。我假设你可以编码 getLocation
因为你的例子已经有了这个。
最后一件事,您也可以在项目实例中调用 setter 而不是创建新的。我建议不要这样做,因为您会给电话添加其他人可能不会想到的副作用。它通常是错误的来源。但是,您仍然可以这样做:)
希望对您有所帮助
我得到一个搜索项列表。此列表中的每个元素都存在一个纬度和经度。对于这些坐标,我使用采用这两个值的 googleService 和 returns 具有此位置名称(城市名称)的 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
}
}
});
实际上你不应该真的改变你的 searchItems
而是用新信息创建新的。这是为了加强不可变性,这对 Rx 来说非常重要。
有不止一种方法可以做到这一点,但这里有一种可能的方法。您需要该项目来调用您的 Google 服务,因此您不能使用 zip
或其任何朋友。因此,让我们像您拥有的那样保留第一位,并获得发出每个搜索项的可观察对象:
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
的结果映射到具有结果位置的项目。请注意,在这里您如何通过 google?
现在在 map 函数中,您可以使用诸如 createWithLocation(item, getLocation(jsonObject))
之类的函数,也可以使用诸如构建器模式之类的函数:
item.toBuilder()
.location(getLocation(jsonObject))
.build();
另请注意,在订阅者 onNext
上,您现在有一个 Item
而不是 JsonObject
并且位置已填充。我假设你可以编码 getLocation
因为你的例子已经有了这个。
最后一件事,您也可以在项目实例中调用 setter 而不是创建新的。我建议不要这样做,因为您会给电话添加其他人可能不会想到的副作用。它通常是错误的来源。但是,您仍然可以这样做:)
希望对您有所帮助