Обновление LiveData + Room в неактивной модели

Я пытаюсь наблюдать за изменениями в БД, сделанными из другого фрагмента.

У меня есть фрагмент A (содержащий recyclerView с элементами) с ViewModel, который имеет внутри свойство LiveData из Room база данных.

Как это: val allItems: LiveData<List <Item>> = repo.getAll()

Если я открою новый фрагмент (назовем его B) из фрагмента A и сделаю там repo.insert(item), я ожидаю, что наблюдатель LiveData сработает allItems при возврате к фрагменту A. Но этого не происходит.

Как это исправить?

Конечно, я могу получать данные в onViewCreated() каждый раз, когда открываю фрагмент A, но я считаю, что должен быть лучший способ.

class CharactersViewModel : BaseViewModel() {
    private val db get() = AppDatabase.getDB(MyApplication.application)

    private val repo = CharacterRepository(viewModelScope, db.characterDao())

    val characters: LiveData<List<Character>> = repo.getAll()
}
class CharacterRepository(
    private val scope: CoroutineScope,
    private val dao: CharacterDao
) {
    fun getAll() = dao.getAll()

    fun getById(itemId: Int) = dao.getById(itemId)

    fun insert(item: Character) = scope.launch {
        dao.insert(item)
    }

    fun update(item: Character) = scope.launch {
        dao.update(item)
    }

    fun delete(item: Character) = scope.launch {
        dao.delete(item)
    }
}
@Dao
interface CharacterDao {
    fun getAll(): LiveData<List<Character>>

    fun getById(itemId: Int) : LiveData<Character>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(item: Character)

    @Update(onConflict = OnConflictStrategy.REPLACE)
    suspend fun update(item: Character)

    @Delete
    suspend fun delete(item: Character)
}

Примечание. Похоже, это связано с тем, что ViewModel фрагмента A в настоящее время неактивен. И проблема не из-за viewLifecycleOwner, поскольку наблюдающийForever также не уведомляется.

Upd: Только что обнаружил проблему, ответ прилагается.


person Skarlet    schedule 23.01.2021    source источник
comment
пожалуйста, поделитесь своим кодом   -  person Alireza aslami    schedule 24.01.2021


Ответы (1)


Было при получении экземпляра базы данных.

fun getDB(appContext: Context) = Room.databaseBuilder(
    appContext,
    AppDatabase::class.java, DB_NAME
).build()

Я решил проблему, сделав его одноэлементным, поэтому теперь он возвращает тот же экземпляр БД.

companion object {
    @Volatile
    private var INSTANCE: AppDatabase? = null

    @Synchronized
    fun getDB(context: Context): AppDatabase {
        // if the INSTANCE is not null, then return it, otherwise create the database
        return INSTANCE ?: run {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                DB_NAME
            ).build()
            INSTANCE = instance

            instance
        }
    }

}
person Skarlet    schedule 23.01.2021