对于我的Android应用程序,我需要一个Observable,它聚合来自7个不同搜索的结果并作为单个集合发出。
ListMultimap<Content, SearchResult>
,其中Content
是搜索结果类型的枚举,SearchResult
是用于显示搜索结果的视图模型界面。这是我如何做到的,但有哪些我不知道的RxJava操作符可以做得更干净吗?
public Observable<ListMultimap<Content, SearchResult>> getSearchResults(final CharSequence charSequence) {
return Observable.just(charSequence)
.map(new Func1<CharSequence, ListMultimap<Content, SearchResult>>() {
@Override
public ListMultimap<Content, SearchResult> call(CharSequence charSequence) {
final String searchTerm = charSequence.toString();
final ListMultimap<Content, SearchResult> data =
MultimapBuilder.enumKeys(Content.class)
.arrayListValues()
.build();
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getSectionPageSearchResults(searchTerm).toBlocking().first())
data.put(Content.SECTION_PAGE, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getAppendixPageSearchResults(searchTerm).toBlocking().first())
data.put(Content.APPENDIX_PAGE, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.FIGURE).toBlocking().first())
data.put(Content.FIGURE, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.TABLE).toBlocking().first())
data.put(Content.TABLE, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getImageSearchResults(searchTerm, ImageType.FORM).toBlocking().first())
data.put(Content.FORM, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getGlossarySearchResults(searchTerm, GlossaryType.ACRONYMS).toBlocking().first())
data.put(Content.ACRONYM, searchResult);
for (SearchResult searchResult : SearchBookmarkableRepoImpl.this.getGlossarySearchResults(searchTerm, GlossaryType.DEFINITIONS).toBlocking().first())
data.put(Content.DEFINITION, searchResult);
return data;
}
});
}
以下是7种搜索方法之一的示例方法签名。每个返回Observable<List<SearchResult>>
如果RxJava有更好的方法来执行此操作,我可以将它们作为单独的SearchResult
而不是List<>
Observable<List<SearchResult>> getSectionPageSearchResults(final String searchWord)
答案 0 :(得分:1)
让我们一步一步。
为了使它更通用,假设你有一个名为anEnum的对象(= SearchResult)和enum(= Content)。
我已经将ArrayListMultimap用于具体的实现,我之前没有使用它,所以如果有更好的方法来添加对象请做。
第一步:map Observable<List<Object>>
至Observable<ArrayListMultimap<anEnum, Object>>
private Observable<ArrayListMultimap<anEnum, Object>> getMultiListSectionPageSearchResults(final String searchWord, anEnum anEnum) {
return getSectionPageSearchResults(searchWord).map(objects -> {
ArrayListMultimap<anEnum, Object> newList = ArrayListMultimap.create();
for (Object o : objects) {
newList.put(anEnum, o);
}
return newList;
});
}
现在您有一个所需格式的列表。
第二步:为所有数据创建observable,假设你有4个
Observable<ArrayListMultimap<anEnum, Object>> multiList1 = getMultiListSectionPageSearchResults("one", anEnum.ONE);
Observable<ArrayListMultimap<anEnum, Object>> multiList2 = getMultiListSectionPageSearchResults("two", anEnum.TWO);
Observable<ArrayListMultimap<anEnum, Object>> multiList3 = getMultiListSectionPageSearchResults("three", anEnum.THREE);
Observable<ArrayListMultimap<anEnum, Object>> multiList4 = getMultiListSectionPageSearchResults("four", anEnum.FOUR);
第三步:merge将它们转换为一个流(如果订单对您很重要,您还可以使用concat)
Observable<ArrayListMultimap<anEnum, Object>> mergedLists = Observable.merge(
multiList1, multiList2, multiList3, multiList4);
第四步:reduce将它们放到一个列表中,我们将使用第一个列表作为将保留所有列表的列表
Observable<ArrayListMultimap<anEnum, Object>> oneList = mergedLists.reduce((l1, l2) -> {
for (anEnum c : l2.keySet()) {
for (Object o : l2.get(c)) {
l1.put(c, o);
}
}
return l1;
});
最后一步:使用数据,single()只是为了确保我们实际获得一个列表
oneList.single().subscribe(this::doSomething);
doSomething:private void doSomething(ArrayListMultimap<anEnum, Object> list)
如果您使用常规列表,转换将会更容易,因为已经有一些方法可以为您执行此操作,例如l1.addAll(l2)
for reduce
答案 1 :(得分:0)
假设您将单个Observable
拆分为每个搜索类型的单独Observable
,您可以使用combining operators或aggregate operators之一来收集所有搜索结果再次成为一个Observable
。这将使您能够并行运行搜索,并且如果您愿意,也可以运行单个搜索。
例如,您可以连接两个Observable
,如下所示:
Observable o1 = Observable.just(1, 2, 3);
Observable o2 = Observable.just(4, 5, 6);
Observable result = o1.concatWith(o2);
result
观察者会发出1, 2, 3, 4, 5, 6
。