我使用rxjava以下列方式执行维护任务:
在我需要定期维护的类中,我使用以下静态预订,这导致Observable在类加载到内存时首次启动,然后按指定的规则间隔启动。
private static Subscription subscription = Observable.timer(0, 5, TimeUnit.SECONDS)
.flatMap(new Func1<Long, Observable<String>>() {
@Override public Observable<String> call(Long aLong) {
// some code
return Observable.just(null);
}
}).subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
.subscribe();
现在我遇到了一种情况,我希望将维护结果报告给用户界面。
通常,我会使用以下架构
Observable.create(new Observable.OnSubscribe<String>() {
@Override public void call(Subscriber<? super String> subscriber) {
// some code
subscriber.onNext(result);
subscriber.onCompleted(); }
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override public void call(String result) {
// write to the UI
}
});
但是这里我们有一个只执行一次的Observable。
对于定期执行的Observable,我找不到在Subscriber中调用Action的方法,这样我就可以使用subscriber.onNext()传递结果。看起来Observable没有合适的签名,可以从timer()获取长时间,同时允许订阅操作。但是知道rxjava我确信有一个技巧; - )
我可以使用zip来压缩Timer Observable和一次性Observable(基本上将两个版本压缩在一起),但我宁愿使用第一个结构,因为它的行为略有不同。
-
我尝试以下列方式将两个版本合并为一个版本:
private static Subscription subscription = Observable.timer(0, 5, TimeUnit.SECONDS)
.flatMap(new Func1<Long, Observable<String>>() {
@Override public Observable<String> call(Long aLong) {
// some code // stays here to ensure there is no concurrency while executing
final String result = "result"; // I store the result in a final variable after some code has been finished
return Observable.create(new Observable.OnSubscribe<String>() {
@Override public void call(Subscriber<? super String> subscriber) {
subscriber.onNext(result); // then I use it in a new Observable and emit it
subscriber.onCompleted(); // not sure if this is needed here (haven't tested this yet)
}
});
}
}).subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
.subscribe(new Action1<String>() {
@Override public void call(String result) {
// so I can finally consume the result on the UI thread
}
});
我创建了一个允许我将结果发送给订阅者的代码,而不是创建和发出“null”Observable。
相当凌乱,但这应该有效,对吗?更简单的解决方案?你有什么想法?
答案 0 :(得分:1)
我不明白你的问题。
您想要使用Observable Timer和其他Observable的相同订阅吗?
也许你可以使用一个主题作为你的Observable之间的桥梁。
Subject<?, ?> bridge = PublishSubject.create();
Observable.timer(5, SECONDS).flatMap(/* whatever*/).mergeWith(bridge).subscribe(/* toDo */);
Observable.create(/* subscription */).subscribe(bridge);
你的“One time Observable”发出的每一个项目都会被推入brige,这将把它推入可以观察到的“计时器”。
这就是你要找的东西吗?
答案 1 :(得分:0)
我知道这是一段时间后添加这个问题的答案。但是,它可能会帮助别人。 据我所知,你想创建一个observable并运行它例如每3秒。所以请在下面找到我的示例(您可以发出像Observable.just这样的现成运算符,甚至可以使用Observable.create运算符创建自己的observable):
Observable.interval(3,TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Long aLong) throws Exception {
return Observable.just("Hello " + Thread.currentThread().getName()+aLong);
/*
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
try{
String data = fetchData("http://www.yahoo.com");
emitter.onNext(data.length()+"");
emitter.onComplete();
}catch (Exception e){
emitter.onError(e);
}
}
});
*/
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("RxResult","-- " + Thread.currentThread().getName() + " -- " +s);
}
});
public String fetchData(String url) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
String inputLine;
String result = "";
while((inputLine = in.readLine()) != null){
result += inputLine;
}
return result.length()+"";
}