Android中RxJava更新ProgressBar:无法逐次间隔更新的问题
解决RxJava更新ProgressBar时进度直接跳满的问题
我来帮你排查下问题根源,再给你几个靠谱的解决方案~
问题原因
你当前代码里的delay(1000, TimeUnit.MILLISECONDS)是给整个Observable序列设置了1秒的延迟,而不是让每个进度值之间间隔500ms。当延迟结束后,Observable.range(0,50)会一次性把0到49的所有数值全部发射出来,所以ProgressBar直接就跳到了49%(接近50%),看起来像是直接跳满了。
解决方案1:使用interval实现定时发射(推荐)
interval操作符天生就是用来每隔指定时间发射递增整数的,非常适合这种进度条更新场景:
// 每隔500ms发射一个值,从0到50(共51个值),对应0%到50%进度 Observable.interval(500, TimeUnit.MILLISECONDS) .take(51) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(progress -> { mProgressBar.setProgress(progress.intValue()); // 可选:进度到50%时可以做一些收尾操作 if (progress == 50) { // do something } });
这里take(51)是因为interval从0开始发射,取51个值正好覆盖0到50,完美匹配你要的0%到50%进度范围。
解决方案2:给每个range元素单独加延迟
如果一定要基于range来实现,可以用concatMap为每个元素单独设置延迟,保证它们依次发射:
Observable.range(0, 51) // 同样取0到50共51个值 .subscribeOn(Schedulers.computation()) // 给每个元素单独添加500ms延迟,concatMap保证顺序执行 .concatMap(progress -> Observable.just(progress) .delay(500, TimeUnit.MILLISECONDS)) .observeOn(AndroidSchedulers.mainThread()) .subscribe(progress -> mProgressBar.setProgress(progress));
concatMap会逐个处理range发射的每个值,每个值都等待500ms后再发射,这样就能实现每隔500ms更新一次进度的效果。
重要提醒:避免内存泄漏
别忘了在页面销毁(比如onDestroy)时及时取消订阅,防止内存泄漏。可以用CompositeDisposable来管理订阅:
private CompositeDisposable mDisposable = new CompositeDisposable(); // 订阅时将Disposable加入管理 mDisposable.add(Observable.interval(500, TimeUnit.MILLISECONDS) .take(51) ... .subscribe(...)); // 在页面销毁时清理 @Override protected void onDestroy() { super.onDestroy(); mDisposable.dispose(); }
内容的提问来源于stack exchange,提问作者Anh Vinh Huỳnh
相关产品推荐
相关产品推荐

