本文不分析操做符的使用方法,主要分析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,而後測試沒有再打印日誌,應該是中止了,再次進入時又從新打印日誌。至此中止定時任務以及延申的問題都解決了,在此記錄一下,但願對採坑的朋友有幫助。圖片