Ich versuche, ohne Erfolg, ein Problem für Tage zu lösen. Ich möchte meine RecyclerView immer dann aktualisieren, wenn sich die Datensätze eines bestimmten Modells in der Datenbank (DB Room) ändern. Ich verwende ViewModel, um die Modelldaten zu verarbeiten, und die Liste der Datensätze wird in LiveData gespeichert.Laden RecyclerView nach Datenänderung mit Room, ViewModel und LiveData
Datenbank
@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
}
Modell
@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)
}
Ansichtsmodell
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
}
}
}
Fragment
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)
}
}
Nun ist meine Frage, warum die Beobachter nur einmal (am Anfang des Fragments) genannt und dann nicht wieder genannt wird? Wie kann ich den Beobachter ständig auf die Änderungen in der Datenbank achten (Einfügen, Aktualisieren, Löschen), damit mein RecyclerView sofort aktualisiert werden kann? Vielen Dank für einen Vorschlag.