Перезагрузите RecyclerView после изменения данных с помощью Room, ViewModel и LiveData
Я безуспешно пытаюсь решить проблему в течение нескольких дней. Я хотел бы обновлять свой recyclerView всякий раз, когда записи конкретной модели изменяются в базе данных (комнате БД). Я использую ViewModel для обработки данных модели, а список записей хранится в LiveData.
База данных
@Database(entities = arrayOf(Additive::class), version = ElementDatabase.DB_VERSION, exportSchema = false)
abstract class ElementDatabase() : RoomDatabase() {
companion object {
const val DB_NAME : String = "element_db"
const val DB_VERSION : Int = 1
fun get(appContext : Context) : ElementDatabase {
return Room.databaseBuilder(appContext, ElementDatabase::class.java, DB_NAME).build()
}
}
abstract fun additivesModels() : AdditiveDao
}
модель
@Entity
class Additive {
@PrimaryKey @ColumnInfo(name = "id")
var number : String = ""
var dangerousness : Int = 0
var description : String = ""
var names : String = ""
var notes : String = ""
var risks : String = ""
var advice : String = ""
}
Dao
@Dao
interface AdditiveDao {
@Query("SELECT * FROM Additive")
fun getAllAdditives() : LiveData<List<Additive>>
@Query("SELECT * FROM Additive WHERE id = :arg0")
fun getAdditiveById(id : String) : Additive
@Query("DELETE FROM Additive")
fun deleteAll()
@Insert(onConflict = REPLACE)
fun insert(additive: Additive)
@Update
fun update(additive: Additive)
@Delete
fun delete(additive: Additive)
}
ViewModel
class AdditiveViewModel(application: Application) : AndroidViewModel(application) {
private var elementDatabase : ElementDatabase
private val additivesModels : LiveData<List<Additive>>
init {
this.elementDatabase = ElementDatabase.get(appContext = getApplication())
this.additivesModels = this.elementDatabase.additivesModels().getAllAdditives()
}
fun getAdditivesList() : LiveData<List<Additive>> {
return this.additivesModels
}
fun deleteItem(additive : Additive) {
DeleteAsyncTask(this.elementDatabase).execute(additive)
}
private class DeleteAsyncTask internal constructor(private val db: ElementDatabase) : AsyncTask<Additive, Void, Void>() {
override fun doInBackground(vararg params: Additive): Void? {
db.additivesModels().delete(params[0])
return null
}
}
}
Фрагмент
class AdditivesFragment : LifecycleFragment() {
private var viewModel : AdditiveViewModel? = null
private var adapter : AdditivesAdapter? = null
companion object {
fun newInstance() : AdditivesFragment {
val f = AdditivesFragment()
val args = Bundle()
f.arguments = args
return f
}
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater?.inflate(R.layout.fragment_additives, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
this.adapter = AdditivesAdapter(ArrayList<Additive>())
this.additives_list.layoutManager = GridLayoutManager(this.context, 2, GridLayoutManager.VERTICAL, false)
this.additives_list.adapter = this.adapter
this.viewModel = ViewModelProviders.of(this).get(AdditiveViewModel::class.java)
this.viewModel?.getAdditivesList()?.observe(this, Observer<List<Additive>> { additivesList ->
if(additivesList != null) {
this.adapter?.addItems(additivesList)
}
})
super.onActivityCreated(savedInstanceState)
}
}
Теперь мой вопрос: почему наблюдатель вызывается только один раз (в начале фрагмента), а затем не вызывается снова? Как я могу заставить наблюдателя постоянно прислушиваться к изменениям в БД (вставлять, обновлять, удалять), чтобы мой recyclerView мог мгновенно обновляться? Большое спасибо за любое предложение.
1 ответ
Вот где вы допустили ошибку:
this.viewModel = ViewModelProviders.of(this).get(AdditiveViewModel::class.java)
вы проходите this
пока ты внутри fragment
что очень беспокоит некоторых людей, потому что это не синтаксическая ошибка, а логическая. Вы должны пройтиactivity!!
вместо этого это будет так:
this.viewModel = ViewModelProviders.of(activity!!).get(AdditiveViewModel::class.java)
У меня была проблема, похожая на вашу, пожалуйста, проверьте ее и посмотрите, поможет ли она вам