简体   繁体   English

Observable.just(doSomeLongStuff())在我订阅observable之前先运行doSomeLongStuff()

[英]Observable.just(doSomeLongStuff()) run doSomeLongStuff() before I subscribe to observable

I have stupid problem with RxJava2. 我对RxJava2有愚蠢的问题。

I need to run two long operations at the same time. 我需要同时运行两个长时间的操作。 I know that I should use Observable.zip() and I use it. 我知道我应该使用Observable.zip()并使用它。

The problem, that my long operations is run one after another and another problem that my long operations starting before I subscribe to them. 问题是,我的长操作一个接一个地运行,另一个问题是我的长操作在订阅它们之前就开始了。

Let's imagine that this is my long operation that I should run async. 让我们想象一下,这是我应该异步运行的长时间操作。

private String doSomethingLong() {
        Random rand = new Random();
        int value = rand.nextInt(5);
        Timber.i("Do something for [%d] sec [%s]", value, Thread.currentThread().getName());
        try {
            Thread.sleep(value * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return String.format(Locale.getDefault(), "Exception [%s]", e.getMessage());
        }
        return String.format(Locale.getDefault(),"Job for [%d] seconds", value);
    }

And let there is a method like test() that will try to make it parallel: 并提供一个类似test()的方法来尝试使其平行:

public void test() {

        final long started = System.currentTimeMillis();
        Observable<String> just1 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
        Observable<String> just2 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());


        Observable.zip(just1, just2, new Func2<String, String, Combined>() {
            @Override
            public Combined call(String s, String s2) {
                return new Combined(s, s2);
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Combined>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Combined combined) {
                long total = System.currentTimeMillis() - started;
                Timber.i("TOTAL [%d]ms [%s]", total, combined.toString());
            }
        });

    }

When I'm trying to run this I observe that two observables just1 and just2 runs one after another... And it's confused me... 当我尝试运行此命令时,我发现两个可观察变量just1和just2依次运行...这让我感到困惑...

But there is another staff that confused me more... I commented Observable.zip and noticed that just1 and just2 started method doSomethingLong() before I subscribed to them... 但是还有另一位员工让我更加困惑...我评论了Observable.zip,并注意到在我订阅它们之前,just1和just2启动了方法doSomethingLong()。

Let me show: 让我展示:

public void test() {

        final long started = System.currentTimeMillis();
        Observable<String> just1 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());
        Observable<String> just2 = Observable.just(doSomethingLong()).subscribeOn(Schedulers.newThread());


//        Observable.zip(just1, just2, new Func2<String, String, Combined>() {
//            @Override
//            public Combined call(String s, String s2) {
//                return new Combined(s, s2);
//            }
//        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Combined>() {
//            @Override
//            public void onCompleted() {
//
//            }
//
//            @Override
//            public void onError(Throwable e) {
//
//            }
//
//            @Override
//            public void onNext(Combined combined) {
//                long total = System.currentTimeMillis() - started;
//                Timber.i("TOTAL [%d]ms [%s]", total, combined.toString());
//            }
//        });

    }

This code make almost same - it's run two times doSomethingLong() one after another... 这段代码几乎相同-一次执行两次doSomethingLong()...

What I'm expect: 1. I need that doSomethingLong() methods run parallel 2. I'm asking to explain why those methods runs before I start subscribe them. 我的期望:1.我需要doSomethingLong()方法可以并行运行2.我要在我开始订阅它们之前解释为什么这些方法运行。 3. How should I write me code well in this situation. 3.在这种情况下,我应该如何编写代码。 I want that doSomethingLong() methods do not called before I subscribe to them. 我希望在我订阅它们之前不调用doSomethingLong()方法。

Thanks a lot. 非常感谢。 Hope that I explain problem well. 希望我能很好地解释问题。

Observable.just doesn't run anything when you subscribe. 订阅时Observable.just不会运行任何内容。 It emits the elements when you subscribe, but your doSomethingLong will run as soon as you pass it as an argument. 订阅时它将发出元素,但是doSomethingLong将在您将其作为参数传递后立即运行。 That's normal and it's how the language works. 那是正常的,这就是语言的工作方式。

What you're looking for is a way to say return this when we subscribe, but also only run it at that time and hopefully on a background thread. 您正在寻找的是一种在我们订阅时就返回此内容的方式,但也只能在当时并希望在后台线程上运行它。

There are a couple of answers for this, here are some: 为此,有两个答案:

Using defer 使用延迟

There's an operator called defer which takes a lambda which will be executed once you subscribe: 有一个叫做defer的运算符,它接受一个lambda,一旦您订阅,该lambda将被执行:

Observable.defer(() ->  doSomethingLong())

This will only execute doSomethingLong when you subscribe 订阅时只会执行doSomethingLong

Using fromCallable 使用fromCallable

You can create an observable from a lambda. 您可以从lambda创建可观察对象。 This is known as fromCallable : 这称为fromCallable

Observable.fromCallable(() -> doSomethingLong())

Similarly, this will only run doSomethingLong when you subscribe 同样,仅在您订阅时运行doSomethingLong

Using create 使用创建

I think this is perhaps the most discouraged way of doing it, since there's a couple of things you have to deal with, but I think for the she of completeness it's ok to mention: 我认为这可能是最不鼓励这样做的方法,因为您必须处理几件事,但是对于完整的她,我可以提一下:

Observable.create( emitter -> {
    if(emitter.isDisposed()) return;

    emitter.onNext(doSomethingLong());
    emitter.onComplete();
});

Again, I'm sure there's more ways of doing this. 同样,我确信还有更多的方法可以做到这一点。 I just wanted to explain the issue and give some options. 我只是想解释这个问题,并提供一些选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM