简体   繁体   English

Android Room Database-LiveData-更新/插入/删除,跳过观察者(回调)

[英]Android Room Database - LiveData - Update/Insert/Delete, skip observer (callback)

I'm new in Room Database, and recently I faced a problem that has to do with modifying the App's database (update/insert/delete) without causing the callback in observer to be fired. 我是Room Database的新用户,最近我遇到了一个问题,该问题与修改应用程序的数据库(更新/插入/删除)有关,而不会导致触发观察器中的回调。

This is the Dao class for my model: 这是我的模型的Dao类:

@Dao
interface ReceiptRowDao {

    @Query("SELECT * FROM my_model ")
    fun getMyModels(): LiveData<MutableList<MyModel>>

    @Update
    fun update(receiptRow: ReceiptRow): Int
}

My Database class: 我的Database类:

@Database(
        entities = [
            (MyModel::class)
        ],
        version = 1,
        exportSchema = false
)
abstract class AppDatabase: RoomDatabase() {

    abstract fun myModelDao(): MyModelDao
}

Usage: 用法:

class MyClass {
    val db: AppDatabase = Room
                    .databaseBuilder(mContext, AppDatabase::class.java, "my_db")
                    .allowMainThreadQueries()
                    .build()

    fun test() {
        val myLiveData = db.myModelDao.getMyModels()
        myLiveData!!.observe(this, Observer { data ->
                ...
                val item = data.get(0)
                item.id = 4
                // This update should not cause a callback
                db.myModelDao().update(item)
                ...
            })
    }
}

In the MyClass , the update instruction will cause an infinite loop , since an update to MyModel, will fire the observer. MyClass ,由于对MyModel的更新将触发观察者,因此update指令将导致无限循环 Then the code inside the observer will run again. 然后,观察者内部的代码将再次运行。 This will do another update. 这将进行另一次更新。 This will fire the observer again and so on... 这将再次触发观察者,依此类推...

In such a scenario, is there a way to do the update of a model, but to skip the observers that might be listening for changes? 在这种情况下,是否有一种方法可以进行模型更新,但是可以跳过可能正在监听更改的观察者?

I think what you could do is just simply check whether data is already in the database. 我想你可以做的是只是简单的检查是否data已经在数据库中。 Like 喜欢

 fun test() {
    val myLiveData = db.myModelDao.getMyModels()
    myLiveData!!.observe(this, Observer { data ->
            ...
            val item = data.get(0);
            // This update should not cause a callback
            if (!db.myModelDao().itemExists(item){
            db.myModelDao().update(item)
            }
            ...
        })
}

this is the database class which holds the DAO classes along with its instance 这是数据库类,其中包含DAO类及其实例

@Database(entities = {Weight.class, DailyConsumption.class, DrinkType.class}, version = 1, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {

// DAO classes
public abstract WeightDao weightDao();
public abstract DailyConsumptionDao dailyConsumptionDao();
public abstract DrinkTypeDao drinkTypeDao();

private static MyDataBase dataBase;

public static MyDataBase getInstance(Context context){
    if (null== dataBase){
        dataBase= buildDatabaseInstance(context);
    }
    return dataBase;
}

private static MyDataBase buildDatabaseInstance(Context context) {
    return Room.databaseBuilder(context,
            MyDataBase.class,
            Constants.DB_NAME)
            .allowMainThreadQueries().build();
}
}

and the part where you want to insert the data in database takes two parameters. 您要在数据库中插入数据的部分采用两个参数。 one database class object and the entities. 一个数据库类对象和实体。 I have designed the entities classes like a model class which you can use to set and get values inside main class. 我已将实体类设计为类似于模型类,可用于在主类中设置和获取值。

 dailyConsumption = new DailyConsumption();  // entity class
 myDataBase = MyDataBase.getInstance(this);
    dailyConsumption.setIcon(mIcon);
    dailyConsumption.setQuantity(mQuantity);
    dailyConsumption.setTime(strTime);
    dailyConsumption.setIsSelected(0);
    dailyConsumption.setDrinkUnit(drinkUnit);
    dailyConsumption.setDateTime(insertionDate);
    dailyConsumption.setDate(date);
    setDailyDataBase(myDataBase, dailyConsumption);

and the method setDailyDatabase just calls the database class to insert the entity setDailyDatabase方法仅调用数据库类以插入实体

  private void setDailyDataBase(MyDataBase dataBase, DailyConsumption dailyConsumption) {

   // query takes parameters to update respective  columns
    myDataBase.dailyConsumptionDao().updateItem(mId, mQuanity, mTime, date);
}

For your issue, i would suggest you following way for observing LiveData & updation of your Model : 对于您的问题,我建议您按照以下方式观察LiveData和更新Model

class MyClass {
val db: AppDatabase = Room
                .databaseBuilder(mContext, AppDatabase::class.java, "my_db")
                .allowMainThreadQueries()
                .build()

fun getDataObserver() = db.myModelDao.getMyModels()

fun test(item: MyModel) {
    db.myModelDao().update(item)
}
}

This will help you seperate your observer logic from update logic , now call getDataObserver() method where you want to observe data and use your test() method when you want to update your Model. 这将帮助您将观察者逻辑更新逻辑分开,现在在要观察数据的地方调用getDataObserver()方法,并在要更新模型时使用test()方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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