Java 如何清理使用.create(OnSubscribe)方法创建的可观察对象
我有以下代码,它使用Java 如何清理使用.create(OnSubscribe)方法创建的可观察对象,java,rx-java,Java,Rx Java,我有以下代码,它使用Observable.create(OnSubscribe)方法创建一个自定义的Observable: public class Main { public static void main(String[] args) { Subscription subscription = Observable .create(subscriber -> { Timer timer
Observable.create(OnSubscribe)
方法创建一个自定义的Observable
:
public class Main {
public static void main(String[] args) {
Subscription subscription = Observable
.create(subscriber -> {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
subscriber.onNext("tick! tack!");
}
};
timer.scheduleAtFixedRate(task, 0L, 1000L);
})
.subscribe(System.out::println);
new Scanner(System.in).nextLine();
System.err.println("finishing");
subscription.unsubscribe();
}
}
可观察对象使用计时器每秒发出一个字符串。当用户按enter键时,订阅将被取消
但是,计时器仍在执行。我怎样才能取消计时器?我想某处一定有个钩子,但我找不到
在.NET上,
create
方法将返回一个IDisposable
,我可以将其作为停止计时器的实现。我不知道如何将它映射到RxJava,因为它的subscribe
方法是void
您可以添加在取消订阅流时调用的代码。为此,您必须在创建
方法中将新的订阅
添加到订户
:
subscriber.add(new Subscription() {
@Override
public void unsubscribe() {
// stop the timer here
}
@Override
public boolean isUnsubscribed() {
// is the stream unsubscribed ?
return false;
}
});
在向订户发送新值之前,可以检查订户是否已取消订阅。如果已取消订阅,则停止计时器:
Subscription subscription = Observable
.create(subscriber -> {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
if (subscriber.isUnsubscribed()) {
// stop timer
} else {
subscriber.onNext("tick! tack!");
}
}
};
timer.scheduleAtFixedRate(task, 0L, 1000L);
})
.subscribe(System.out::println);
因此,上面的组合将完成这项工作:
public class Main {
public static void main(String[] args) throws InterruptedException {
Subscription subscription = Observable.create(subscriber -> {
Timer timer = new Timer();
subscriber.add(Subscriptions.create(() -> {
timer.cancel();
}));
TimerTask task = new TimerTask() {
@Override
public void run() {
if (!subscriber.isUnsubscribed())
subscriber.onNext("tick! tack!");
}
};
timer.scheduleAtFixedRate(task, 0L, 1000L);
}).subscribe(System.out::println);
System.err.println("finishing");
subscription.unsubscribe();
Thread.sleep(10000);
}
这是一个更为惯用的RxJava示例,它用更少的代码做同样的事情:
Subscription subscription = Observable
.interval(1000, TimeUnit.MILLISECONDS)
.map(n -> "tick! tack!")
.subscribe(System.out::println);
Thread.sleep(3000);
System.err.println("finishing");
subscription.unsubscribe();
一个更具声明性(且更易于阅读)的解决方案是使用以下方法:
Observable obs=可观测的。使用(
//资源工厂:
()->新定时器(),
//可观察工厂:
计时器->可观察。创建(订户->{
TimerTask任务=新的TimerTask(){
公开募捐{
订户.onNext(“滴答!滴答!”);
}
};
timer.scheduleAtFixedRate(任务,0L,1000L);
}),
//处置行动:
timer->timer.cancel()
);
您可以声明从属资源(计时器)是如何创建的,如何使用它来创建可观察的,以及如何处理它,RxJava将负责在订阅时创建计时器,在取消订阅时处理它。我正在寻找类似的解决方案,我在RxAndroid中发现了以下代码: 看起来您不需要使用
可观察。使用完成清理步骤。相反,您似乎可以添加另一个订阅服务器来进行清理
Observable .create(subscriber -> {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
subscriber.onNext("tick! tack!");
}
};
subscriber.add(Subscriptions.create(() -> {
timer.cancel();
}));
timer.scheduleAtFixedRate(task, 0L, 1000L);
})
调用subscribe
时,此Subscription
是否将Subscription
返回给我?或者它是另一个我无法直接访问的版本?另外,isUnsubscribed
的实现应该是什么样子?硬编码的false
可能是错误的?是否类似于subscriber.isUnsubscribed()
正确?它将不同于Subscription
。isUnsubscribed
可能看起来像运行布尔值的isUnsubscribed(){return running;}
。查看BooleanSubscription
:它可以使用isUnscribedCode
:subscriber.add(BooleanSubscription.create(()->timer.cancel())创建订阅代码>谢谢,有道理。在RxJava中是“佳能”方式吗?似乎比在.NET中要复杂得多。一个订阅者有两个订阅(“标准”订阅和我自己创建并添加的订阅)这一事实会破坏一些行为吗?就像只有一个订阅未订阅,另一个未订阅,状态不一致,行为未定义?经过一些调查和代码阅读,我想我现在可以回答我自己的问题了:返回的订阅(实际上,订阅者
实例,作为订阅者实现订阅
)维护一个订阅列表
(间接地,通过订阅列表
实例),它的unsubscribe
方法迭代所有订阅并取消订阅。因此,无论向订阅服务器添加多少订阅,它们都会同时取消订阅,并且状态将保持一致。在“通过create创建可观察项”下( )老实说,我不认为所有的例子都是好的。例如:50.times{I->if(!aSubscriber.unsubscribed){aSubscriber.onNext(“value{I}”)}
无论如何都会迭代50次,只是不会调用doNext()对于某些值,现在,我不知怎么地认为一个习惯“代码>订阅< /代码>有点干净,甚至更冗长。是的,有点粗鄙。我知道RXJAVA计时器。问题更一般,关于任何资源的清理,我只是使用了一个定时器,因为IndoTrx.com页面使用它作为一个例子。谢谢NoNethes。毫无意义。