RxJava定时器点击按钮B二次启动无响应问题排查求助
问题原因与解决方案
嘿,这个问题我之前也碰到过!咱们一步一步拆解为啥第二次点击按钮没反应:
核心问题1:time变量没有重置
第一次定时器跑完后,time已经变成0了对吧?第二次点击按钮调用timerStart()时,刚进入accept方法就判断time > 0不成立,直接执行hideTimer()——所以看起来啥反应都没有,其实是它直接跳过了倒计时逻辑,立刻隐藏了TimerView。
核心问题2:重复订阅导致资源泄漏+逻辑混乱
每次点击按钮,你都会创建一个新的Observable.interval并添加到CompositeDisposable里,但旧的Observable并没有被停止!第一次的定时器在time到0之后,还是会每秒发射一次事件,每次都走else分支执行hideTimer()。而且多个订阅同时修改同一个time变量,逻辑只会越来越混乱。
修复方案:给你两个靠谱的实现方式
方案1:重置时间+自动终止Observable
用take()操作符让Observable在发射指定次数后自动完成,同时每次启动前重置time并清空旧订阅:
@Override public void timerStart() { // 1. 重置倒计时时间为59秒 time = 59; // 2. 清空之前的所有订阅,避免多个Observable同时运行 getCompositeDisposable().clear(); getCompositeDisposable() .add(Observable.interval(0, 1000, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) // 只发射60次(0到59秒,共60次),发射完自动完成 .take(60) .subscribe( aLong -> { String timer = String.format("%s:%s", "00", time <= 9 ? "0" + time : String.valueOf(time)); getMvpView().updateTimer(timer); time--; }, throwable -> getMvpView().hideTimer(), // Observable完成时触发,隐藏TimerView () -> getMvpView().hideTimer() ) ); }
方案2:单独管理每个定时器(支持中途取消)
如果需要更精准的控制(比如中途可以手动取消倒计时),可以把当前的Disposable存起来,每次启动前先取消旧的:
private Disposable timerDisposable; @Override public void timerStart() { // 先取消旧的定时器 if (timerDisposable != null && !timerDisposable.isDisposed()) { timerDisposable.dispose(); } time = 59; timerDisposable = Observable.interval(0, 1000, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .take(60) .subscribe( aLong -> { String timer = String.format("%s:%s", "00", time <= 9 ? "0" + time : String.valueOf(time)); getMvpView().updateTimer(timer); time--; }, throwable -> getMvpView().hideTimer(), () -> getMvpView().hideTimer() ); getCompositeDisposable().add(timerDisposable); }
这样修改后,不管你点多少次按钮B,每次都会先清理旧的定时器、重置时间,然后启动新的倒计时流程,就不会出现没反应的情况啦!
内容的提问来源于stack exchange,提问作者Abhishek Tiwari
相关产品推荐
相关产品推荐

