如果 RxJava 可观察性需要很长时间,你如何显示微调器?

2022-09-04 04:14:23

我觉得必须有人尝试过这个,但是如果一个可观察的需要很长时间,我就找不到一个好方法来做某事。

这就是我想要的流程。

Start a search.
If the search takes longer than some time,
    show a spinner or show progress bar.
When finished do subscription action and hide spinner/progress bar.

我能想到的最接近的就像一个Zip

manager.search(searchTerm)
       .zip(Observable.Timer(1, TimeUnit.SECONDS))
       .subscribe(
           // if the search is non null then we are good
           // if the long time is non 0 we need to show spinner
       );

还有更好的事情要做吗?我一整天都在尝试,但没有成功。在一个完美的世界里,我觉得我想要这样的东西

manager.search(searchTerm)
       .timeout(i -> /* do timeout stuff */, 1, TimeUnit.SECONDS)
       .subscribe(item -> /* do search result stuff */);

答案 1

您可以通过超时发布搜索可观察性来执行此操作:

Observable<Integer> source = Observable.just(1).delay(5, TimeUnit.SECONDS);

source
.doOnSubscribe(() -> System.out.println("Starting"))
.publish(o -> 
    o.timeout(1, TimeUnit.SECONDS, Observable.<Integer>fromCallable(() -> {
        System.out.println("Spinning...");
        return null;
    })).ignoreElements().mergeWith(o)
)
.toBlocking()
.subscribe(v -> {
    System.out.println("Hide spinner if shown.");
    System.out.println(v);
});

这是通过将源拆分为两个热通道来实现的:第一个通道将运行一个操作员,当超时时,启动另一个Observable,副作用显示旋转控制。其中一种方法是使用它并忽略其结果(这也避免了重复)。第二个通道将保持不变,并与超时通道合并以提供实际值。timeoutfromCallable


答案 2

今天我发现有点奇怪但有效的解决方案。想法是使用间隔而不是计时器。

    fun <T> base_delayed_progress_observable(source: Observable<T>): Observable<T>
    {
        val timer = Observable.interval(100, TimeUnit.MILLISECONDS) //Creates observable that will emit Long++ each 100 miliseconds
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(
                    {
                        if (it == 10L)//Here we check current timer value. For example here i check if it is 1 second gone (100 miliseconds * 10 = 1 second)
                        {
                            //here we put all we need to show progress/spinner an so on
                        }
                    })

        return Observable.zip(source, timer,
            BiFunction<T, Long, T> { t1, t2 ->
                //Here we return our original Obervable zipped with timer
                //Timer will be cancelled when our source Observable gets to OnComplete
                return@BiFunction t1
            }).doFinally(
            {
                //Here we can dismiss all progress dilogs/spinner
            })
    }

推荐