我试图拥抱RxJava的荣耀并将其集成到我的应用程序中。我已经编写了以下代码来添加漫画,其累积成本不超过定义的预算。为实现这一目标,我编写了2个实现。
Observable.create()
主要是因为订阅和背压的复杂性而不鼓励如果在Observable.create()
暂时将Subscription和Backpressure处理放在一边,我希望得到关于哪些实现在性能,内存消耗和简单性方面更好的反馈?
第一次实施:
Observable<Integer> filterObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Timber.d("filterComicsAccordingToBudget():subscribe");
int pageCountOfComicsWithInBudget = 0;
double totalCost = 0.0;
for(MarvelComic comic : getMarvelComicsList()) {
totalCost += Double.valueOf(comic.getPrice());
Timber.d("totalCost: %s budget: %s priceOfComic: %s", totalCost, budget, comic.getPrice());
if(totalCost > budget) {
break;
}
pageCountOfComicsWithInBudget += Integer.valueOf(comic.getPageCount());
Timber.d("pageCount: %s price: %s comicName: %s totalPages: %s", comic.getPageCount(), comic.getPrice(), comic.getTitle(), pageCountOfComicsWithInBudget);
e.onNext(pageCountOfComicsWithInBudget);
}
e.onComplete();
}
});
filterObservable.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
int comicCount = 0;
int pageCountOfComicsWithInBudget = 0;
@Override
public void onSubscribe(Disposable d) {
Timber.d("filterComicsAccordingToBudget():onSubscribe");
}
@Override
public void onNext(Integer pageCountOfComicsWithInBudget) {
Timber.d("filterComicsAccordingToBudget():onNext");
comicCount++;
}
@Override
public void onError(Throwable e) {
Timber.e("onFilterComicsForBudget:onError() %s", e);
}
@Override
public void onComplete() {
Timber.d("filterComicsAccordingToBudget():onComplete");
}
}
});
第二次实施:
Observable.fromIterable(getMarvelComicsList())
.map(new Function<MarvelComic, HashMap<String, Double>>() {
HashMap<String, Double> myMap = new HashMap<String, Double>();
double count = 0;
@Override
public HashMap<String, Double> apply(@NonNull MarvelComic marvelComic) throws Exception {
myMap.put("price", Double.valueOf(marvelComic.getPrice()));
myMap.put("pageCount", Double.valueOf(marvelComic.getPageCount()));
myMap.put("comicsCount", count++);
return myMap;
}
})
.takeWhile(new Predicate<HashMap<String, Double>>() {
double sum;
@Override
public boolean test(@NonNull HashMap<String, Double> map) throws Exception {
Timber.e("sum is: %s", sum);
return (sum += map.get("price")) < 5.00;
}
})
.subscribe(new Observer<HashMap<String, Double>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(HashMap<String, Double> map) {
Timber.e("value in onNext is: %s %s %s", map.get("pageCount"), map.get("price"), map.get("comicsCount"));
}
@Override
public void onError(Throwable e) {
Timber.e("onError()!!! %s",e);
}
@Override
public void onComplete() {
Timber.e("onComplete()!!!");
}
});
我有点喜欢第一次实施,因为它比我以前更加迫切,而且对我来说似乎不那么笨拙但是考虑到我对RxJava的知识有限,我可能完全错了。
答案 0 :(得分:5)
我会避免为这种操作创建自定义Observable
。您可以使用普通的RxJava运算符完成所需的一切。
在飞行中我会做这样的事情:
private Observable<Double> getLimitObservable(final double budget) {
return Observable.fromIterable(getMarvelComicsList())
.scan(0D, (aDouble, marvelComic) -> aDouble + marvelComic.getPrice())
.takeWhile(aDouble -> aDouble < budget)
.skip(1);
}
上面的代码使用scan
(也称为累加器)运算符来跟踪漫画的总价格。更多细节here。所以,现在从新的Observable返回一个double(表示总量)。在此之后,我们使用takeWhile
来停止项目的发射,直到条件保持为真。最后我跳过了第一个项目,因为上面提到的Observable将发出至少一个项目(在条件可以验证之前)。
Observable.zip(getLimitObservable(500d), Observable.fromIterable(getMarvelComicsList()), (aDouble, marvelComic) -> marvelComic)
.subscribe(marvelComic -> Log.d("test", "comic: " + marvelComic.getName()));
现在我将之前的observable与一个新的observable(使用zip运算符)组合在一起,为每一对项目生成一个新项目(一个来自第一个observable,一个来自第二个),这样你就会得到许多项目等于从两个可观察者发出的最小项目数。更多详情here
这将打印列表中第一个漫画的列表,直到达到预算限制。
我打赌有更好的解决方案,但这只是一个例子。