簡體   English   中英

android -MutableLiveData沒有觀察到新數據

[英]android -MutableLiveData doesn't observe on new data

我正在使用mvvm和android架構組件,我是這個架構的新手。

在我的應用程序中,我從Web服務獲取一些數據並在recycleView中顯示它,它工作正常。

然后我有一個用於添加新數據的按鈕,當用戶輸入數據時,它進入Web服務,然后我必須獲取數據並再次更新我的適配器。

這是我的活動代碼:

 private fun getUserCats() {
    vm.getCats().observe(this, Observer {
        if(it!=null) {
            rc_cats.visibility= View.VISIBLE
            pb.visibility=View.GONE
            catAdapter.reloadData(it)

        }
    })
}

這是視圖模型:

class CategoryViewModel(private val model:CategoryModel): ViewModel() {

private lateinit var catsLiveData:MutableLiveData<MutableList<Cat>>

fun getCats():MutableLiveData<MutableList<Cat>>{
    if(!::catsLiveData.isInitialized){
        catsLiveData=model.getCats()
    }
    return catsLiveData;
}

fun addCat(catName:String){
    model.addCat(catName)
}

}

這是我的模型類:

class CategoryModel(
    private val netManager: NetManager,
    private val sharedPrefManager: SharedPrefManager) {

private lateinit var categoryDao: CategoryDao
private lateinit var dbConnection: DbConnection
private lateinit var lastUpdate: LastUpdate

fun getCats(): MutableLiveData<MutableList<Cat>> {
    dbConnection = DbConnection.getInstance(MyApp.INSTANCE)!!
    categoryDao = dbConnection.CategoryDao()
    lastUpdate = LastUpdate(MyApp.INSTANCE)

    if (netManager.isConnected!!) {
        return getCatsOnline();
    } else {
        return getCatsOffline();
    }
}

fun addCat(catName: String) {
    val Category = ApiConnection.client.create(Category::class.java)
    Category.newCategory(catName, sharedPrefManager.getUid())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    { success ->
                        getCatsOnline()
                    }, { error ->
                Log.v("this", "ErrorNewCat " + error.localizedMessage)
            }
            )
}

private fun getCatsOnline(): MutableLiveData<MutableList<Cat>> {
    Log.v("this", "online ");
    var list: MutableLiveData<MutableList<Cat>> = MutableLiveData()
    list = getCatsOffline()

    val getCats = ApiConnection.client.create(Category::class.java)
    getCats.getCats(sharedPrefManager.getUid(), lastUpdate.getLastCatDate())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    { success ->
                        list += success.cats
                        lastUpdate.setLastCatDate()

                        Observable.just(DbConnection)
                                .subscribeOn(Schedulers.io())
                                .subscribe({ db ->
                                    categoryDao.insert(success.cats)
                                })

                    }, { error ->
                Log.v("this", "ErrorGetCats " + error.localizedMessage);
            }
            )

    return list;
}

我從活動中調用getCat,它進入模型並將其發送到我的Web服務,成功后我調用getCatsOnline方法從webservice再次獲取數據。

當我調試時,它獲取數據但它沒有通知我的活動,我的意思是觀察者沒有在我的活動中被觸發。

我怎樣才能解決這個問題 ? 我的代碼出了什么問題?

LiveDataRxJava使用中,你已經犯了幾個不同的重要錯誤,以及MVVM設計本身。


LiveData和RxJava

請注意, LiveDataRxJava是流。 它們不是一次性使用,因此您需要觀察相同的LiveData對象,更重要的是,需要更新相同的LiveData對象。

如果你看一下getCatsOnline()方法,每次調用該方法時,它都會創建一個全新的LiveData實例。 該實例與之前的LiveData對象不同,因此無論是否正在偵聽前一個LiveData對象,都不會通知新的更改。

還有一些額外的提示:

  • getCatsOnline()您正在訂閱另一個訂閱者內部的Observable 這是將RxJava視為回叫的初學者的常見錯誤。 這不是回叫,你需要鏈接這些電話。

  • 不要在模型層中subscribe ,因為它會中斷流,您無法確定何時取消訂閱。

  • 使用AndroidSchedulers.mainThread()是沒有意義的。 不需要在Model層中切換到主線程,特別是因為LiveData觀察者只在主線程上運行。

  • 不要將MutableLiveData暴露給其他層。 只需返回LiveData

我要指出的最后一件事是你一起使用RxJavaLiveData 既然你是兩者都是新手,我建議你堅持使用其中一個。 如果您必須同時使用兩者,請使用LiveDataReactiveStreams正確橋接這兩者。


設計

如何解決所有這些問題? 我猜你要做的是:

(1)查看需求類別 - >(2)從服務器獲取類別 - >(3)用新貓創建/更新可觀察list對象,並將結果獨立保存在DB中 - >(4) list實例應通知活動自動。

很難正確地將其關閉,因為您必須手動創建和更新此list實例。 您還需要擔心保留此list實例的位置和時間。

更好的設計是:

(1)查看需求類別 - >(2)從DB獲取LiveData並觀察 - >(3)從服務器獲取新類別並使用服務器響應更新DB - >(4)視圖會自動通知,因為它一直在觀察DB !

這更容易實現,因為它具有這種單向依賴性:視圖 - >數據庫 - >服務器

示例CategoryModel:

class CategoryModel(
    private val netManager: NetManager,
    private val sharedPrefManager: SharedPrefManager) {

    private val categoryDao: CategoryDao
    private val dbConnection: DbConnection
    private var lastUpdate: LastUpdate // Maybe store this value in more persistent place..


    fun getInstance(netManager: NetManager, sharedPrefManager: SharedPrefManager) {
        // ... singleton
    }


    fun getCats(): Observable<List<Cat>> {
        return getCatsOffline();
    }

    // Notice this method returns just Completable. Any new data should be observed through `getCats()` method.
    fun refreshCats(): Completable {
        val getCats = ApiConnection.client.create(Category::class.java)

        // getCats method may return a Single
        return getCats.getCats(sharedPrefManager.getUid(), lastUpdate.getLastCatDate())
            .flatMap { success -> categoryDao.insert(success.cats) } // insert to db
            .doOnSuccess { lastUpdate.setLastCatDate() }
            .ignoreElement()
            .subscribeOn(Schedulers.io())
    }


    fun addCat(catName: String): Completable {
         val Category = ApiConnection.client.create(Category::class.java)

         // newCategory may return a Single
         return Category.newCategory(catName, sharedPrefManager.getUid())
             .ignoreElement()
             .andThen(refreshCats())
             .subscribeOn(Schedulers.io())
        )
    }
}

我建議您閱讀應用程序架構指南和Google提供的其中一個livesata-mvvm示例應用程序

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM