Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RxJava平面映射链接请求_Android_Retrofit_Rx Java_Chaining_Flatmap - Fatal编程技术网

Android RxJava平面映射链接请求

Android RxJava平面映射链接请求,android,retrofit,rx-java,chaining,flatmap,Android,Retrofit,Rx Java,Chaining,Flatmap,我正在使用RxJAva对一个获取Rss提要的应用程序进行改造,但Rss并不包含所有信息,因此我使用jsoup解析每个项目链接,以检索图像和文章描述。现在我这样使用它: public Observable<Rss> getDumpData() { return newsAppService.getDumpData() .flatMap(rss -> Observable.from(rss.channel.items) .ob

我正在使用RxJAva对一个获取Rss提要的应用程序进行改造,但Rss并不包含所有信息,因此我使用jsoup解析每个项目链接,以检索图像和文章描述。现在我这样使用它:

public Observable<Rss> getDumpData() {
    return newsAppService.getDumpData()
            .flatMap(rss -> Observable.from(rss.channel.items)
            .observeOn(Schedulers.io())
            .flatMap(Checked.f1(item -> Observable.just(Jsoup.connect(item.link).get())
            .observeOn(Schedulers.io())
            .map(document -> document.select("div[itemprop=image] > img").first())
                    .doOnNext(element -> item.image = element.attr("src"))
            )))
            .defaultIfEmpty(rss)
            .ignoreElements()
            .observeOn(Schedulers.io())
            .subscribeOn(AndroidSchedulers.mainThread());
}
公共可观测getDumpData(){
返回newsAppService.getDumpData()
.flatMap(rss->Observable.from(rss.channel.items)
.observeOn(Schedulers.io())
.flatMap(Checked.f1(item->Observable.just(Jsoup.connect(item.link).get())
.observeOn(Schedulers.io())
.map(document->document.select(“div[itemprop=image]>img”).first()
.doOnNext(element->item.image=element.attr(“src”))
)))
.defaultIfEmpty(rss)
.ignoreElements()
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread());
}
我在这一行得到一个错误:
defaultIfEmpty(rss)

它无法识别平面地图的rss。当我移动flatmap括号中的
defaultIfEmpty(rss)
时,我有另一个错误,即返回类型必须更改为元素。他们有什么解决办法吗

不能将一个
RxJava
参数(
flatMap
lambda参数)的内部参数与另一个运算符参数(
defaultIfEmpty
)混合使用

首先,创建一个helper函数以保持主反应流更干净:

private Observable<List<Item>> getDetails(List<Item> items) {
    return Observable.from(items)
               .observeOn(Schedulers.io())
               .flatMap(Checked.f1(item ->
                   Observable.zip(
                       Observable.just(item),
                            Observable.just(Jsoup.connect(item.link).get())
                           .observeOn(Schedulers.io())
                           .map(document -> document.select("div[itemprop=image] > img").first()),
                           (itemInner, element) -> {
                                itemInner.image = element.attr("src");
                                return itemInner;
                           }
                   )
               ))
               .toList();
}
private observeable getDetails(列表项){
可观察的返回。来自(项目)
.observeOn(Schedulers.io())
.flatMap(选中.f1(项目->
可观察的.zip(
可观察。仅(项目),
Observable.just(Jsoup.connect(item.link.get())
.observeOn(Schedulers.io())
.map(document->document.select(“div[itemprop=image]>img”).first(),
(项目内部,元素)->{
itemInner.image=element.attr(“src”);
返回项目内部;
}
)
))
.toList();
}
然后重新格式化主功能:

newsAppService.getDumpData()
    .flatMap(rss ->
        Observable.zip(
            Observable.<Rss>just(rss),
            getDetails(rss.channel.items),
            (rssInner, items) -> {
                rssInner.channel.items = items;
                return rss;
            }).onErrorResumeNext((throwable -> Observable.just(rss))
        )
    )
    .observeOn(Schedulers.io())
    .subscribeOn(AndroidSchedulers.mainThread());
newsAppService.getDumpData()
.flatMap(rss->
可观察的.zip(
可观察。公正(rss),
获取详细信息(rss.channel.items),
(罪人,物品)->{
rssInner.channel.items=项目;
返回rss;
}).onErrorResumeNext((可丢弃->可观察的.just(rss))
)
)
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread());

希望我正确地瞄准了你。它可能不起作用,因为我无法测试它,但是我希望你能理解。我使用
.zip
的原因在于,您不能失去对当前解析的
项的引用
rss

首先,您需要摆脱与observeOn的所有并发,并使用subscribeOn

.observeOn(Schedulers.io())

请考虑使用AndroidScheduler的观察,如果要将数据从另一个线程同步回事件循环。通常,您会在订阅observeOn之前使用observeOn,以便同步回ui循环并更改ui信息

.observeOn(AndroidSchedulers.mainThread())
其次,不建议对管道中的对象进行变异。每次都应该返回一个新对象

.doOnNext(element -> item.image = element.attr("src"))
考虑到前两点,我试图重构您的解决方案。我使用的是RxJava2-RC5

flatMap操作符有许多重载。其中一个函数提供了将传入值和创建值压缩在一起的函数

Observable<Rss> rssItemObservable = newsService.getDumpData()
                .flatMap(rss -> getRssItemInformation(rss).subscribeOn(Schedulers.io()),
                        (r, rItemList) -> {
                            Rss rInterim = new Rss();
                            rInterim.items = rItemList;
                            return rInterim;
                        });
Observable rssItemObservable=newservice.getDumpData()
.flatMap(rss->getRssItemInformation(rss).subscribeOn(Schedulers.io()),
(r,rItemList)->{
Rss-rInterim=新的Rss();
rInterim.items=rItemList;
返回rInterim;
});
用于检索Rss中每个项目的信息的帮助方法。请考虑使用最大并发的超载,因为默认情况下它会同时订阅每个流。因此flatMap将创建许多http请求

private Observable<List<RssItem>> getRssItemInformation(Rss rss) {
        return Observable.fromIterable(rss.items)
                .flatMap(rssItem -> getImageUrl(rssItem).subscribeOn(Schedulers.io()), (rItem, img) -> {
                    RssItem item = new RssItem();
                    printCurrentThread("merge1");
                    item.image = img;
                    item.link = rItem.link;
                    return item;
                }).toList().toObservable();
}
私有可观察getRssItemInformation(Rss){
返回Observable.fromIterable(rss.items)
.flatMap(rssItem->getImageUrl(rssItem).subscribeOn(Schedulers.io()),(rItem,img)->{
RssItem item=新的RssItem();
printCurrentThread(“合并1”);
item.image=img;
item.link=rItem.link;
退货项目;
}).toList().toObservable();
}
用于检索图像url的帮助方法。返回observable并不是对并发性的固执己见。如果发生错误,将返回一个空字符串作为默认值

private Observable<String> getImageUrl(String link) {
           return Observable.fromCallable(() -> Jsoup.connect(link).get())
                .map(document -> document.select("div[itemprop=image] > img").first())
                .map(element -> element.attr("src"))
                .onErrorResumeNext(throwable -> {
                    return Observable.just("");
                });
}
私有可观察getImageUrl(字符串链接){
返回Observable.fromCallable(()->Jsoup.connect(link.get())
.map(document->document.select(“div[itemprop=image]>img”).first()
.map(元素->元素属性(“src”))
.onErrorResumeNext(可丢弃->{
可观察的返回。仅(“”);
});
}

您可以查看github.gist上的完整示例:

通过将
flatMap
参数传递到
defaultIfEmpty
参数,尝试实现什么?你想捕获一个异常吗?@R.Zagórski它只是为了防止发生错误,它会发出可观察到的源代码。你希望从
newsAppService.getDumpData()
或从你的转换中获得图像时会发生错误吗?是的@R.Zagórski我希望它能从转换中抛出一个异常。它工作得很好,但是我不太理解代码,我会阅读zip文档,你救了我