转换ReplaySubject的值

时间:2016-02-17 07:23:28

标签: rx-java

聪明的Java人!今天早上我很慢,我希望你可以帮忙。 (我不是流媒体和编程的新手,但对Java和Rx来说并不陌生)

基本上,我有一个带有userName属性的简单对象Credentials。我收到这个作为ReplaySubject,我想将其转换为ReplaySubject。即基本上只是将ReplaySubject转换为ReplaySubject。这是表达我想要的内容的代码,但是错误的类型错误压倒了尚未用于Java的不良认知功能。

 public ReplaySubject<String> getUserId() {
   return getCredentials(context).map(credentials -> credentials.userName);
 }

 private ReplaySubject<Credentials> getCredentials() {

错误:

Error:(52, 43) error: incompatible types: no instance(s) of type variable(s) R exist so that Observable<R> conforms to ReplaySubject<String>
where R,T are type-variables:
R extends Object declared in method <R>map(Func1<? super T,? extends R>)
T extends Object declared in class Observable

1 个答案:

答案 0 :(得分:1)

是的,该错误消息确实使问题听起来比实际上更复杂。

重点是:map返回Observable,而不是ReplaySubject。 (即使您拨打Observable的原始map实际上是ReplaySubject。)

但是,这不是一个真正的问题,只需将getUserId的返回类型更改为Observable<String>即可。基础ReplaySubject仍会重播每个新订阅者的所有值。

试试这个:

package com.example;

import rx.Observable;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subjects.ReplaySubject;

public class ReplaySubjectTest {

    public static void main(String[] args) {

        ReplaySubject<Integer> originalSubject = ReplaySubject.create();

        Observable<Integer> doubledObservable = originalSubject.map(new Func1<Integer, Integer>() {
            @Override
            public Integer call(Integer integer) {
                return integer * 2;
            }
        })
                .doOnNext(new LoggingAction1<Integer>("after doubling"));

        originalSubject.onNext(1);

        doubledObservable.subscribeOn(Schedulers.io())
                .subscribe(new LoggingSubscriber<Integer>("1"));

        originalSubject.onNext(2);
        originalSubject.onNext(3);

        doubledObservable.subscribeOn(Schedulers.io())
                .subscribe(new LoggingSubscriber<Integer>("2"));

        // wait for two seconds before stopping main thread
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

编辑:抱歉,我忘了提及:您需要将自己的LoggingSubscriber和LoggingAction替换为您自己的...

另外:你真的打了ReplaySubject(重放以前的所有值)还是BehaviourSubject(只重播最近的值)就足够了?

编辑2:如果您预计Credentials(以及UserId)会在生命周期内经常更改,最好使用BehaviourSubject代替ReplaySubject。这样,每个Subscriber只会立即获得最新的UserId以及任何后续的新UserId。使用ReplaySubject,您还可以获得以前的所有 UserIds,并且您的onNext的{​​{1}}将会快速连续调用,甚至可能不相关更多。如果您只使用新的UserId更新本地UI,这可能不是问题。但是,如果您要为每个新的UserId加载最近观看的电影(或其他内容)列表,可能会出现更多问题 - 这会触发很多网络请求,只有最后一个会发出对你有意思。

我希望这有点意义......

还有一件事:我不太熟悉JavaScript中的Promise,但你确定在这里需要Subscriber吗?您是否了解了创建Subject的更简单方法,例如Observablesjust