博客 / 詳情

返回

Android app中這樣用flow更方便-刷新token獲取數據

背景

移動app中展示的數據多數都是通過服務器接口獲取的,當接口數據與用户相關時,服務端接口會要求客户端把用户信息通過接口發送到服務器。普遍的做法是把用户登錄後的token數據發送給服務器的接口。考慮到安全問題,token都有過期時間,token過期後服務端就不能通過這個token查詢用户的具體信息了。為了刷新過期token,服務端會提供一個刷新token的接口給客户端使用。

問題分析

由於要求上傳token的服務端接口會有很多,所以這些接口的調用都需要考慮token過期失效問題。
這些接口調用的異常處理中需要增加token過期處理,在token過期的情況下觸發token刷新處理。
token刷新後觸發接口的重試請求。
如何使用flow實現
首先我們實現一個刷新token的flow。

private val refreshTokenFlow = flow {
        if (expiredToken) {
            cachedToken = serverApi.refreshToken("token-0")
            expiredToken = false
        }
        emit(cachedToken)
    }

expiredToken變量代表token是否過期,實際開發過程中這個變量的值應該根據過期時間計算得出的。cachedToken變量保存着最新的token值,請求用户相關信息的接口時可以把這個token傳遞給服務端用於查詢。我們可以看到cachedToken的值是通過調用服務端提供的刷新接口獲取的。這個flow最終發射的是最新的token值,同時我們也看到這個flow調用刷新接口的邏輯只有token過期時才會被調用。
第二步定義請求用户相關數據的flow

    private fun getDataFlow(token: String) = flow {
        emit(serverApi.getDataViaToken(token))
    }

由於請求用户數據的接口依賴token的值,所以這個flow是通過方法生成的。flow的生成也比較簡單,它直接調用服務端的接口並將數據發射出去。

第三步將刷新token的flow和請求用户數據的flow展開

    private val userDataFlow = refreshTokenFlow.flatMapConcat{token->
        getDataFlow(token)
    }

flatMapConcat方法將前面定義的兩個流拼接在一起,這時我們要是收集拼接後的userDataFlow,refreshTokenFlow會被收集,flatMapConcat方法接收到 refreshTokenFlow發射的token後開始收集getDataFlow方法返回的flow。這樣連個flow的依賴關係通過flatMapConcat完美實現了。

第四步實現token過期重試機制

 private val userDataFlow = refreshTokenFlow.flatMapConcat{token->
     getDataFlow(token)
 }.retryWhen { cause, attempt ->
     if (attempt > 1) {
         false
     } else if(cause is InvalidTokenException) {
         expiredToken = true
         true
     }else{
         false
     }
 }.catch {
     msgView.text = it.message
 }

基於第三步的flow拼接我們添加了retryWhen和cach兩個塊。retryWhen塊用於實現重試機制,參數cause是前面流程發生的異常,參數attempt代表重試的次數,返回值true代表進行重試,返回值false代表不進行重試。在retryWhen塊中我們可以通過cause的類型來判斷是否要重試,當cause為InvalidTokenException時代表token過期,所以進行重試並且重置了token過期expiredToken。為了避免無限地進行重試,這裏限制重試次數為一次。catch塊處理不進行重試時的邏輯,一般會將出錯的信息顯示到界面上。

總結

通過flow的方式實現token刷新機制相較於傳統的方式有如下優勢:

邏輯簡單明瞭,刷新流程簡單清晰直觀。flow操作符語義簡單明瞭,鏈式的方式聲明處理過程更容易理解,沒有複雜的嵌套。
通過聲明的方式定義了刷新流程,同時也支持通過聲明的方式擴展已有流程。比如這裏拼接了刷新token的flow和獲取用户數據的flow。
重試機制可以根據不同的依賴token接口進行定製處理,接口的重試機制更加靈活方便。這裏沒有針對重試流程定義新的flow,但在實際應用中我們可以為重試流程定義flow,然後將flow拼接在已有flow後。這樣我們可以在不同的地方重用重試流程的flow。
我的公眾號已經開通,公眾號會同步發佈。
歡迎關注我的公眾號

————————————————
版權聲明:本文為CSDN博主「mjlong123123」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/mjlong1...

user avatar backofhan 頭像 xuesi_595299e4a2381 頭像 jijige_6231ef0f1d144 頭像
3 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.