关于Observable interval定时任务停止问题

风流意气都作罢 提交于 2020-04-10 21:55:29

本文不分析操作符的使用方法,主要分析interval轮询中如何来停止。

最近在项目中使用RxJava,RxAndroid;主要运用于网络请求,但是项目中有用到定时任务,每隔20s去更新数据,因此想到RxJava中有定时器操作符,再加上已经引入RxJava,链式请求就完成了,详见代码:

Observable.interval(0, 20, TimeUnit.SECONDS)
	.doOnSubscribe {
		mDisposable = it
	}
	.flatMap {
		return@flatMap DataUtils.API_SERVICE.getQrCode(userId)
	}
	.map {
		val body = it.string()
		val str = body.substring(body.indexOf(",") + 1)
		val decodedString = Base64.decode(str, Base64.DEFAULT)
		return@map BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
	}
	.compose(ThreadFromUtils.defaultSchedulers())
	.subscribe({
		dismissProgressDialog()
		qr_code.setImageBitmap(it)
	}, {
		dismissProgressDialog()
		var msg = when (it) {
			is SocketTimeoutException -> "网络连接超时!"
			is ConnectException -> "连接不上服务器,请检查网络链接!"
			is IOException -> "流连接意外结束,请稍候重试!"
			is HttpException -> "网络出现异常,请稍候重试!"
			is JsonSyntaxException -> "数据解析出现错误!"
			else -> it.localizedMessage
		}
		if (msg.isNullOrEmpty()) {
			msg = "出现错误,请稍候重试!"
		}
		showErrorToast(msg)
	})

(竟然么有Kotlin选项,将就看看吧。)链式请求也在项目中运用很多,这里用到flatmap和map:flatmap主要返回获取二维码请求->然后在map中生成bitmap->最后展示。这种方法看着舒服,但是也有问题:当接收到error的时候,定时器就会退出。因此不得不改变写法,详见代码:

Observable.interval(0, 20, TimeUnit.SECONDS)
	.doOnSubscribe {
		mDisposable = it
	}
	.subscribeOn(Schedulers.computation())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe {
		refreshQrCode()
	}

就是把获取二维码代码的请求在定时器每发送一次onNext中去执行,这样就解决了当接收到error的时候,定时器就会退出的问题。但是测试提出Bug说,离开这个页面还在刷新二维码数据。因此不得不在onPause里面把mDisposable.cancel()取消掉,如果可以也就万事大吉了;不想这样不仅没有用,还引出一个Bug,心里那个憋屈吖,只能打碎牙齿往肚子里咽。Bug截图如图示: Bug图片

经细看是因为刷新二维码都会有一个弹框等待,由于Activity已经销毁,所以Dialog add window 失败。 想着先骗过测试吧,于是在获取二维码数据时,增加了一个判断,if(activity != null && !activity!!.isFinishing)时去获取,否则不获取二维码数据。

这样只是应付测试,自己还要找结局方案,于是搜索Observable interval stop,在StackOverflow是找到解决方案,最后修改为,详见代码:

Observable.interval(0, 20, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
	.takeWhile {
		!mStop
	}
	.subscribe {
		refreshQrCode()
	}

mStop是是否停止标志,在onResume()中赋值为false,在onPause()中赋值为true,然后测试没有再打印日志,应该是停止了,再次进入时又重新打印日志。至此停止定时任务以及延申的问题都解决了,在此记录一下,希望对采坑的朋友有帮助。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!