RxJava:flatMap中的if/else操作

Yuk*_*ida 3 java rx-java

我尝试获取并呈现如下的一些数据

原始数据类

  @Data @AllArgsConstructor class Category {
    String name;
    List<String> items;
  }
Run Code Online (Sandbox Code Playgroud)

演讲课

  @Data @AllArgsConstructor class ViewModel {
    public static final int TYPE_HEADER = 0;
    public static final int TYPE_ITEM = 1;
    int type;
    String category;
    String itemName;
  }
Run Code Online (Sandbox Code Playgroud)

以下代码是请求并将订阅数据转换为表示对象.

  Observable.create(new Observable.OnSubscribe<Category>() {
      @Override public void call(Subscriber<? super Category> subscriber) {
        subscriber.onNext(new Category("1", Lists.newArrayList("", "a", "b")));
        subscriber.onNext(new Category("2", Lists.newArrayList("")));// this data does not output
        subscriber.onNext(new Category("3", Lists.newArrayList("c", "", "d")));
        subscriber.onNext(new Category("4", Lists.newArrayList("e", "f", "")));
      }
    }).flatMap(new Func1<Category, Observable<ViewModel>>() {
      @Override public Observable<ViewModel> call(Category category) {

        // TODO make this block to one line

        // 1. clean response data and transform to ViewModel    
        List<ViewModel> cleanedItems = Lists.newArrayList(
            Observable.from(category.getItems()).filter(new Func1<String, Boolean>() {
              @Override public Boolean call(String s) {
                return s != null && !s.isEmpty();
              }
            }).map(new Func1<String, ViewModel>() {
              @Override public ViewModel call(String item) {
                return new ViewModel(ViewModel.TYPE_ITEM, null, item);
              }
            }).toBlocking().toIterable());

        if (cleanedItems.isEmpty()) {
          // 2. case : skip
          return Observable.empty();
        } else {
          // 3. case : add header and cleaned data
          return Observable.concat(
              Observable.just(new ViewModel(ViewModel.TYPE_HEADER, category.getName(), null)),
              Observable.from(cleanedItems));
        }
      }
    }).subscribe(new Action1<ViewModel>() {
      @Override public void call(ViewModel viewModel) {
        // render data
        System.out.println(viewModel.toString());
      }
    });
Run Code Online (Sandbox Code Playgroud)

产量

ViewModel(type=0, category=1, itemName=null)
ViewModel(type=1, category=null, itemName=a)
ViewModel(type=1, category=null, itemName=b)
ViewModel(type=0, category=3, itemName=null)
ViewModel(type=1, category=null, itemName=c)
ViewModel(type=1, category=null, itemName=d)
ViewModel(type=0, category=4, itemName=null)
ViewModel(type=1, category=null, itemName=e)
ViewModel(type=1, category=null, itemName=f)
Run Code Online (Sandbox Code Playgroud)

我尝试将1,2,3,(注释)语句写入1行(或更可读的方式),但我不知道. defaultIfEmpty在这种情况下,运营商似乎不会使用.

有人有任何想法吗?

Bri*_*ley 11

这个怎么样:

    public static <T, R> Func1<? super T, ? extends Observable<? extends R>> ternary(
        Func1<T, Boolean> predicate,
        Func1<? super T, ? extends Observable<? extends R>> ifTrue,
        Func1<? super T, ? extends Observable<? extends R>> ifFalse) {
        return (item) -> predicate.call(item)
                ? ifTrue.call(item)
                : ifFalse.call(item);
    }
Run Code Online (Sandbox Code Playgroud)

你像这样使用它:

    .map(CharSequence::toString)
    .distinctUntilChanged()
    .flatMap(ternary(Strings::notNullOrEmpty,
        (kw) -> userRelationshipApi.searchFollowing(kw, null),
        (kw) -> Observable.just(selectedUserListAdapter.getUsers())))
    .subscribe(...)
Run Code Online (Sandbox Code Playgroud)