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
相关产品推荐
相关产品推荐

