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。毫无意义。