我怎样才能组合rx.可观测搜索结果从不同的可观测到一个单一的可观测



对于我的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)

让我们一步一个脚印。

为了使其更通用,假设您有一个名为anEnum的对象(=SearchResult(an和enum(=Content(。

我已经使用ArrayListMultimap进行了具体的实现,我以前从未使用过它,所以如果有更好的方法向它添加对象,请这样做。

第一步:将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;
    });
    }

现在您有了一个所需格式的列表。

第二步:为所有数据创建可观察性,假设你有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);

第三步:将它们合并为一个流(如果订单对你很重要,你也可以使用concat(

        Observable<ArrayListMultimap<anEnum, Object>> mergedLists = Observable.merge(
            multiList1, multiList2, multiList3, multiList4);

第四步:将它们缩减为一个列表,我们将使用第一个列表作为容纳所有的列表

        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);

where doSomething:private void doSomething(ArrayListMultimap<anEnum, Object> list)

如果你要使用常规列表,转换会容易得多,因为已经有一些方法可以为你做到这一点,比如l1.addAll(l2)减少

假设您将单个Observable拆分为每个搜索类型的单独Observable,则可以使用组合运算符或聚合运算符之一将所有结果再次收集到单个Observable中。这将给你带来能够并行运行搜索的好处,如果你想的话,你也可以运行单独的搜索。

例如,您可以连接两个Observable,如下所示:

Observable o1 = Observable.just(1, 2, 3);
Observable o2 = Observable.just(4, 5, 6);
Observable result = o1.concatWith(o2);

可观测到的CCD_ 15将发射CCD_。

相关内容

  • 没有找到相关文章

最新更新