在Android中使用RxJava "validate-then-insert"模式更好吗?



用户从ui输入一个url,然后我的演示者对其进行验证,如果有效,则将其插入数据库,否则显示错误;我的解决方案如下所示:

@Override
public void addFeed(final String uri) {
    Observable.create(new Observable.OnSubscribe<Boolean>() {
        @Override
        public void call(Subscriber<? super Boolean> subscriber) {
            //may contain some database query,if it has,how should i do ?
            subscriber.onNext(uri.startsWith(FeedFetcher.FEED_SCHEME) && !uri.startsWith(FeedFetcher.HTTP_SCHEME));
            subscriber.onCompleted();
        }
    }).doOnNext(new Action1<Boolean>() {
        @Override
        public void call(Boolean aBoolean) {
            //insert into db
            if (aBoolean)
                mFeedModel.add(uri);
        }
    }).subscribe(new Action1<Boolean>() {
        @Override
        public void call(Boolean aBoolean) {
            if (aBoolean){
                mFeedInputView.hideInputError();
            }else{
              mFeedInputView.showInputError(R.string.url_format_error);
            }
        }
    });
}

**更新**

if (uri.startsWith(FeedFetcher.FEED_SCHEME) ||  uri.startsWith(FeedFetcher.HTTP_SCHEME)) {
        mFeedInputView.hideInputError();
        mChannelModel.isChannelExists(uri)
                .subscribeOn(Schedulers.computation())
                .observeOn(Schedulers.io())
                .flatMap(new Func1<Boolean, Observable<RssChannel>>() {
                    @Override
                    public Observable<RssChannel> call(Boolean aBoolean) {
                        if (aBoolean)
                            return mChannelModel.add(uri);
                        return Observable.empty();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<RssChannel>() {
                    @Override
                    public void call(RssChannel channel) {
                        mFeedInputView.addUrlSuccess();
                    }
                });
    } else {
        mFeedInputView.showInputError(R.string.url_format_error);
    }

但我认为将 if(aBoolean) 放在 flapmap 中不是一个漂亮的解决方案。

怎么样:

public void addFeed(String uri) {
    Observable.just(uri)
            .first(new Func1<String, Boolean>() {
                @Override
                public Boolean call(String uri) {
                    return uri.startsWith(FeedFetcher.FEED_SCHEME) && !uri.startsWith(FeedFetcher.HTTP_SCHEME);
                }
            })
            .subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {
                    mFeedInputView.hideInputError();
                }
                @Override
                public void onError(Throwable e) {
                    mFeedInputView.showInputError(R.string.url_format_error);
                }
                @Override
                public void onNext(String s) {
                    mFeedModel.add(uri);
                }
            });
}

first()运算符将根据筛选规则筛选出收到的无效 URI,如果未找到有效的 uri(在您的情况下,如果作为参数传递的 uri 无效),则会抛出NoSuchElementException

仅当 URI 有效时,才会调用onCompleted(),以便您可以安全地在那里调用hideInputError()。 只有在发生错误时才会调用onError()而不是onCompleted(),因此在那里进行错误处理是安全的。最后,当 uri 有效时将调用onNext(),因为first()运算符忽略无效的 uri,因此可以安全地将其保存在那里。

请注意,我从方法声明中删除了 final 属性。这里不需要它,因为您正在使用 just() 将 uri 本身传递到链中。

另外值得注意的是,您不必为了它而使用RxJava。在您的情况下,如果您不需要异步运行,这可能是一个更干净的解决方案:

public void addFeed(String uri) {
    if (uri.startsWith(FeedFetcher.FEED_SCHEME) && !uri.startsWith(FeedFetcher.HTTP_SCHEME)) {
        mFeedInputView.hideInputError();
        mFeedModel.add(uri);
    } else {
        mFeedInputView.showInputError(R.string.url_format_error);
    }
}

我宁愿以更实用的方式使用这段代码。

Observable.create(new Observable.OnSubscribe<Boolean>())
          .map(b -> b = false)
          .doOnNext(uri.startsWith(FeedFetcher.FEED_SCHEME) && !uri.startsWith(FeedFetcher.HTTP_SCHEME))
          .map(b -> {
                  mFeedModel.add(uri);
                  b=true;
                  return b;
                   })
          .subscribe(b-> {
                         if(!b){
                            mFeedInputView.showInputError(R.string.url_format_error);
                           }
                          });

最新更新