简体   繁体   中英

Shall I use @DatabaseView in Room with LiveData?

Its working if run query through main thread. If I try to get DatabaseView with Livedata POJO, Its throwing error

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 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
)

My Dao

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

@Insert
fun insertFav(favourite: Favourite)
}

My Repository

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

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

ViewModel

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
}
}

Error throwing when I call this observe in my fragment

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

Tell me how to use DatabaseView with LiveData or kotlin coroutines with this MVVM Pattern.

I need to print that FAVORITE SIZE from my fragment through background thread not from UI thread.

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}")
    }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM