我应该在带有 LiveData 的 Room 中使用@DatabaseView 吗?
Shall I use @DatabaseView in Room with 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.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)
数据库视图class
@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
}
}
当我在我的片段中调用这个 observe 时抛出错误
viewModel.favourites.observe(this, androidx.lifecycle.Observer { favorites ->
favorites?.let {
print("FAVORITE SIZE ${favorites.size}")
}
})
告诉我如何将 DatabaseView 与 LiveData 或 kotlin 协程与此 MVVM 模式结合使用。
我需要通过后台线程而不是 UI 线程从我的片段中打印 FAVORITE SIZE。
onCreateView()
可以为同一个 Fragment 实例调用多次(因为当 Fragment 被放入返回堆栈时视图被销毁,但 Fragment 实例本身被保留)。
在 onCreateView()
中使用 observe()
时,您应该 始终 使用 viewLifecycleOwner
而不是 this
,因为这样可以确保之前的观察者(绑定到上次 onCreateView()
被调用)被正确清理:
viewModel.favourites.observe(viewLifecycleOwner, androidx.lifecycle.Observer { favorites ->
favorites?.let {
print("FAVORITE SIZE ${favorites.size}")
}
})
如果 运行 通过主线程查询,它就可以工作。 如果我尝试使用 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.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)
数据库视图class
@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
}
}
当我在我的片段中调用这个 observe 时抛出错误
viewModel.favourites.observe(this, androidx.lifecycle.Observer { favorites ->
favorites?.let {
print("FAVORITE SIZE ${favorites.size}")
}
})
告诉我如何将 DatabaseView 与 LiveData 或 kotlin 协程与此 MVVM 模式结合使用。
我需要通过后台线程而不是 UI 线程从我的片段中打印 FAVORITE SIZE。
onCreateView()
可以为同一个 Fragment 实例调用多次(因为当 Fragment 被放入返回堆栈时视图被销毁,但 Fragment 实例本身被保留)。
在 onCreateView()
中使用 observe()
时,您应该 始终 使用 viewLifecycleOwner
而不是 this
,因为这样可以确保之前的观察者(绑定到上次 onCreateView()
被调用)被正确清理:
viewModel.favourites.observe(viewLifecycleOwner, androidx.lifecycle.Observer { favorites ->
favorites?.let {
print("FAVORITE SIZE ${favorites.size}")
}
})