You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中用Retrofit2和RxJs实现长轮询:解决首次延迟与仅执行一次问题

问题解决:RxJava长轮询首次延迟+仅执行一次的修复

你的代码里有两个核心问题导致了当前的异常行为:

1. 首次调用延迟的原因

Observable.interval(long initialDelay, long period, TimeUnit unit)的第一个参数是初始延迟时间,你传入2000意味着第一次执行要等待2秒。要实现首次立即执行,需将初始延迟设为0,周期保持2000。

2. 仅执行一次的原因

你调用了.take(1)操作符,它会在获取到第一个事件后直接终止整个Observable流,导致轮询仅执行一次,必须移除这个操作符。

修改后的完整代码

private void getTables(int roomNumber) {
    Observable.interval(0, 2000, TimeUnit.MILLISECONDS, Schedulers.io())
                    .flatMap((Function<Long, ObservableSource<List<Tables>>>) aLong -> RetrofitClient.getInstance().getApi()
                            .getTables(Utils.getTablesURL(ip), String.valueOf(roomNumber))
                            .doOnError(err -> Log.e("Polling", "Error retriving tables: " + err))
                            .onErrorResumeNext(throwable -> Observable.empty()))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<List<Tables>>() {
                private Disposable disposable; // 保存Disposable,用于页面销毁时取消订阅,避免内存泄漏

                @Override
                public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
                    disposable = d;
                }

                @Override
                public void onNext(@io.reactivex.rxjava3.annotations.NonNull List<Tables> tablesList) {
                    if (tablesList != null && !tablesList.isEmpty()) {
                        adapterTables = new AdapterTables(layoutManager, tablesList);
                        adapterTables.setListener(position -> getTableInfo(position, tablesList));
                        recyclerView.setAdapter(adapterTables);

                        recyclerView.setVisibility(View.VISIBLE);
                        containerNoData.setVisibility(View.GONE);
                    }
                }

                @Override
                public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
                    if (adapterTables == null || adapterTables.getItemCount() == 0) {
                        containerNoData.setVisibility(View.VISIBLE);
                        recyclerView.setVisibility(View.GONE);
                    }
                }

                @Override
                public void onComplete() {
                    // 移除take(1)后,除非主动调用dispose,否则onComplete不会触发
                }
            });
}

额外注意事项

  • 务必保存Disposable对象,在页面销毁(如onDestroy方法)时调用disposable.dispose()取消订阅,防止内存泄漏。
  • 当前onErrorResumeNext(throwable -> Observable.empty())会吞掉错误并让轮询继续执行,如果需要在错误时停止轮询,可以移除该操作符,或根据错误类型判断是否终止流。

内容的提问来源于stack exchange,提问作者NiceToMytyuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 10:06:45