兩種給給LiveData添加請求狀態(tài)回調(diào)的方法

最近開發(fā)中一直在使用ViewModel +LiveData 配合來實(shí)現(xiàn)MVVM,LiveData 這個東西確實(shí)挺好用的.但是存在一個問題,看代碼:

//表示一個從后臺拿到的User類型來顯示到UI
val  user  = MultableLiveData<User>()

user 從后臺來,就可能出錯,單單用一個user 是無法通知到UI層出錯的,這時候需要一個變量來標(biāo)記出錯的內(nèi)容,同時如果UI層想要在開始請求時顯示加載動畫,就又需要一個 變量來標(biāo)記開始,這時候代碼就變成了這樣

val  user  = MultableLiveData<User>()
var startState = MultableLiveData<Any>()
var errorState = MultableLiveData<Throwable>()

然后在請求網(wǎng)絡(luò)的回調(diào)中,開始請求數(shù)據(jù)就這樣(為了容易理解,網(wǎng)絡(luò)請求返回采用rxjava 的subscribe 的回調(diào)格式,所以就不要好奇為什么不直接在view 層訂閱 網(wǎng)絡(luò)請求返回的Observable 了,因?yàn)闆]有使用rxjava):

requetUser().subscribe{
      onStart = {startState.value = Any()},
      onNext = {user.postValue(it)},
      onError = {user.postValue(it)}
}

然后在 view層分別觀察這三個狀態(tài):

user.observe(this,Observer{ 回顯...})
startState.observe(this,Observer{開始加載動畫....})
errorState.observe(this,Observer{提示出錯....})

這樣清晰是挺清晰的.如果一個頁面對應(yīng)一個接口還好.但是如果是很復(fù)雜的頁面對應(yīng)多個接口,而且每個接口的開始動畫和出錯提示是分開的,那么我們就需要給每一個接口創(chuàng)建三個liveData,這樣就會有非常多的livedata字段..為了少寫幾個字段,我就想能不能制造一個天生的有開始狀態(tài),出錯狀態(tài),正常狀態(tài)且具有l(wèi)ivedata特性的東東呢,這樣一個接口對應(yīng)一個livedata 字段就好了,于是我就做了如下的封裝

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer

class StateLiveData<T>(value: T?) {
    private val liveData = MutableLiveData<T>(value)
    private var onStart = MutableLiveData<Any>()
    private var onError = MutableLiveData<Throwable>()

    var value: T?
        get() {
            return liveData.value
        }
        set(value) {
            liveData.value = value
        }

    fun postValue(value: T?) {
        liveData.postValue(value)
    }


    fun onStart() {
        onStart.value = Any()
    }

    fun postOnStart() {
        onStart.postValue(Any())
    }

    fun onError(throwable: Throwable) {
        onError.postValue(throwable)
    }


    fun observe(
        lifecycleOwner: LifecycleOwner,
        onNext: OnNext<T>? = null,
        onStart: OnStart? = null,
        onError: OnError? = null
    ) {
        liveData.observe(lifecycleOwner, Observer {
            onNext?.invoke(it)

        })
        this.onError.observe(lifecycleOwner, Observer {
            onError?.invoke(it)
        })

        this.onStart.observe(lifecycleOwner, Observer {
            onStart?.invoke()
        })

    }

}

typealias  OnError = (Throwable) -> Unit

typealias OnStart = () -> Unit

typealias OnNext<T> = (T) -> Unit

每一個 StateLiveData都具有 開始狀態(tài),出錯狀態(tài),正常狀態(tài) 這時候我們就可以這樣寫了

val user = StateLiveData<User>()

然后這樣處理網(wǎng)絡(luò)請求回調(diào):

requestUser().subscribe(
onStart = { user.onStart() },
onNext = {user.value = it},
onError = {user.onError(it) }
)

然后在view層這樣觀測user

user.observe(this,
onNext = {回顯結(jié)果...},
onStart = {加載動畫..},
onError = {錯誤提示...}
)

這樣就用構(gòu)造了一個具備狀態(tài)的livedata了..能夠少寫很多字段了哈哈哈...
這個是簡單的封裝,如果有需要ObserverForever 方法,對著這些方法進(jìn)行一一封裝就好了

另外想少寫字段的方法還有一種就是構(gòu)建一個帶數(shù)據(jù)狀態(tài)的UiState

sealed class UiState() {
    class Start : UiState()
    class Error(val throwable: Throwable) : UiState()
    class Next<T>(val t: T) : UiState()
}

然后User字段這樣聲明

val user = MultableLiveData<UiState<User>>

然后這樣觀測請求結(jié)果

requestUser().subscribe(
onStart = {user.postValue(UiState.Start()) },
onNext = { user.postValue(UiState.Next(it))},
onError = {user.postValue(UiState.Error(it) }
)

在view層這樣觀察

 user.observe(this, Observer{ 
            when(it){
                is UiState.Start -> {加載動畫...}
                is UiState.Error ->{錯誤提示...}
                is UiState.Next<*> -> {
                    it.t as User {回顯結(jié)果...}
                }
            }
        })
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末促煮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子掰派,更是在濱河造成了極大的恐慌霞捡,老刑警劉巖榜揖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郎楼,死亡現(xiàn)場離奇詭異死嗦,居然都是意外死亡煎娇,警方通過查閱死者的電腦和手機(jī)二庵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缓呛,“玉大人,你說我怎么就攤上這事杭隙∮窗恚” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵痰憎,是天一觀的道長票髓。 經(jīng)常有香客問我,道長铣耘,這世上最難降的妖魔是什么洽沟? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蜗细,結(jié)果婚禮上裆操,老公的妹妹穿的比我還像新娘。我一直安慰自己炉媒,他們只是感情好踪区,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吊骤,像睡著了一般缎岗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上白粉,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天传泊,我揣著相機(jī)與錄音,去河邊找鬼鸭巴。 笑死眷细,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奕扣。 我是一名探鬼主播薪鹦,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了池磁?” 一聲冷哼從身側(cè)響起奔害,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎地熄,沒想到半個月后华临,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崖叫,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怕犁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了但绕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片却特。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扶供,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出裂明,到底是詐尸還是另有隱情椿浓,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布闽晦,位于F島的核電站扳碍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏仙蛉。R本人自食惡果不足惜笋敞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荠瘪。 院中可真熱鬧夯巷,春花似錦、人聲如沸巧还。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽麸祷。三九已至澎怒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阶牍,已是汗流浹背喷面。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留走孽,地道東北人惧辈。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像磕瓷,于是被迫代替她去往敵國和親盒齿。 傳聞我的和親對象是個殘疾皇子念逞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容