首页 > 解决方案 > 我应该在 Room 中使用 @DatabaseView 和 LiveData 吗?

问题描述

如果通过主线程运行查询,它的工作原理。如果我尝试使用 Livedata POJO 获取 DatabaseView,它会抛出错误

java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles
    at androidx.lifecycle.LiveData.observe(LiveData.java:197)
    at MyFragment.onCreateView(MyFragment.kt:45)
    at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
    at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
    at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7058)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

数据库视图类

@DatabaseView("SELECT ss_pack.id as id, ss_pack.title as title, ss_pack.primary_value as primaryValue FROM ss_pack JOIN favourite WHERE favourite.ss_pack_id = ss_pack.id")
data class AllFavourites(
    val id: Int,
    val title: String,
    val primaryValue: String
)

我的道

interface FavouriteDao {
@Query("SELECT * from AllFavourites")
fun getFavorites(): LiveData<List<AllFavourites>>

@Insert
fun insertFav(favourite: Favourite)
}

我的仓库

class MyRepository(val favoriteDao: FavoriteDao, val categoryDao: CategoryDao) {

val favourites: LiveData<List<AllFavourites>> = favoriteDao.getFavorites()
val categories: LiveData<List<Category>> = categoryDao.loadAllCategories()
}

视图模型

class MyViewModel(application: Application) : AndroidViewModel(application){
private val myRepository: MyRepository
val favourites: LiveData<List<AllFavourites>>

init {
    val favoriteDao = SDatabase.getDatabase(application, viewModelScope).favoriteDao()
    myRepository = myRepository(favoriteDao, categoryDao)
    favourites = passwordRepository.favourites
}
}

当我在我的片段中调用这个观察时抛出错误

viewModel.favourites.observe(this, androidx.lifecycle.Observer { favorites ->
        favorites?.let {
            print("FAVORITE SIZE ${favorites.size}")
        }
    })

告诉我如何将 DatabaseView 与 LiveData 或 kotlin 协程与此 MVVM 模式一起使用。

我需要通过后台线程而不是 UI 线程从我的片段中打印该 FAVORITE SIZE。

标签: androidmvvmkotlinandroid-livedatadatabase-view

解决方案


onCreateView() can be called multiple times for the same Fragment instance (as the view is destroyed when the Fragment is put on the back stack, but the Fragment instance itself is kept around).

You should always use viewLifecycleOwner rather than this when using observe() in onCreateView() as this ensures that the previous observer (tied to the last time onCreateView() was called) is properly cleaned up:

viewModel.favourites.observe(viewLifecycleOwner, androidx.lifecycle.Observer { favorites ->
    favorites?.let {
        print("FAVORITE SIZE ${favorites.size}")
    }
})

推荐阅读