【问题标题】:Rx-Java: Creating a configurable ObservableRx-Java:创建可配置的 Observable
【发布时间】:2016-10-03 16:24:12
【问题描述】:

我是 RxJava 的新手,我想知道如何创建可配置的 Observable?假设我可以像这样编写一个 DB 到 DB 的传输:

srcDb.getObservable(Bean.class)
     .sql(selectSql)
     .params(selectParams)
     .subscribe(
          trgDb.getSubscriber(Bean.class)
               .sql(insertSql)
     );

我已经可以使用订阅者做到这一点,但是我怎样才能以与 Observable 本身相同的方式获得一些小配置?

【问题讨论】:

  • 你不能轻易地在核心 Rx API 中添加你自己的方法,但是你可以做的是用同样流畅的写作风格编写你自己的构建器,并让这些构建器返回一个可观察的结束。这样做,您将能够保持流畅的写作。

标签: java rx-java observable configurable


【解决方案1】:

有两种方法可以做到这一点:

选项 #1:让您自己的对象进行配置,然后使用 execute()query()toObservable() 切换域:

 srcDb
 .find(Bean.class)
 .sql(selectSql)
 .params(selectParams)
 .execute()
 .subscribe(
      trgDb.getSubscriber(Bean.class)
           .sql(insertSql)
 );

选项#2:使用.compose() 重用常用操作:

srcDb
.getObservable(Bean.class)
.compose(addSQLParameters())
.subscribe(
      trgDb.getSubscriber(Bean.class)
           .sql(insertSql)
 );

 <T> Transformer<T,T> addSQLParameters() {
   return obs -> obs.sql(selectSql).params(selectParams);
 }

我建议您使用选项 #1,因为它可以更好地管理您的代码部分。

【讨论】:

  • 你和乔尔(连同他的评论)可能是对的。我尝试使用反射进行一些实验,以从父类公开 onSubscribe 字段,这实际上让我可以做我想做的事,但这不是一个干净的解决方案:-)。无论如何,如果 RxJava 为声称他们“知道自己在做什么”的开发人员提供带有 getOnSubscribe() 方法的某些版本的 Observable 那就太好了:-D。
  • 您可能对 RxJavaHooks#setOnObservableCreate 感兴趣 - 但请记住,这适用于 所有 可观察对象。 IMO 您遇到 XY 问题 - 只需在创建 observable 之前进行配置。
  • 谢谢,我会调查的:-)。
【解决方案2】:

也许我找到了一种可以接受的解决方法。看来我在这里需要做的是在 Observable 实例化本身之外进行双重绑定。例如。我需要一个相互依赖的 DbObservable 和 DbOnSubscribe 对,如下所示:

DbObservable 类:

public class DbObservable<T> extends Observable<T> {

    //Some parameter
    private String sql;

    protected DbObservable(DbOnSubscribe<T> onSub) {
        super(onSub);
    }

    //Getter for DbOnSubscribe
    public String getSql() {
        return sql;
    }

    //Chain parameter modifier
    public DbObservable<T> sql(String sql) {
        this.sql = sql;
        return this;
    }
}

DbOnSubscribe 类:

public class DbOnSubscribe<T> implements Observable.OnSubscribe<T> {

    private DbObservable<T> dbObservable;

    @Override
    public void call(Subscriber<? super T> subscriber) {
        String sql = dbObservable.getSql(); //Access SQL param
        subscriber.onNext( (T) sql ); //Use subscriber
        subscriber.onCompleted();
    }

    //Set back-reference
    public void setDbObservable(DbObservable<T> dbObservable) {
        this.dbObservable = dbObservable;
    }
}

最后是我们假设的 DbConnector 类:

public class DbConnector {

    public DbObservable<String> getObservable() {
        DbOnSubscribe<String> onSub = new DbOnSubscribe<String>();
        DbObservable<String> obs = new DbObservable<>(onSub);
        onSub.setDbObservable(obs);
        return obs;
    }
}

所以当我尝试的时候......

public class DbObservableTest {

    public static void main(String[] args) {
        DbConnector srcDb = new DbConnector();

        srcDb.getObservable()
                .sql("some SQL")
                .subscribe(System.out::println);
    }
}

...它确实有效!它打印出“一些 SQL”。

结论

  1. 如果您想要超级干净并且不介意增加一两行代码,请选择 Joel 和 Tassos Bassoukos 建议的构建器。
  2. 如果你不怕更复杂的代码(应该总是封装在某个地方),并且你真的希望这些参数在你自己的 Observable 中,你可以尝试双重绑定的方式
  3. 还有更多选择吗?

【讨论】:

    猜你喜欢
    • 2013-12-12
    • 2015-09-21
    • 2020-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多