本文不分析操做符的使用方法,主要分析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截图如图示: 日志
经细看是由于刷新二维码都会有一个弹框等待,因为Activity已经销毁,因此Dialog add window 失败。 想着先骗过测试吧,因而在获取二维码数据时,增长了一个判断,if(activity != null && !activity!!.isFinishing)时去获取,不然不获取二维码数据。code
这样只是应付测试,本身还要找结局方案,因而搜索Observable interval stop,在StackOverflow是找到解决方案,最后修改成,详见代码:blog
Observable.interval(0, 20, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) .takeWhile { !mStop } .subscribe { refreshQrCode() }
mStop是是否中止标志,在onResume()中赋值为false,在onPause()中赋值为true,而后测试没有再打印日志,应该是中止了,再次进入时又从新打印日志。至此中止定时任务以及延申的问题都解决了,在此记录一下,但愿对采坑的朋友有帮助。图片