【问题标题】:Android Room Database - LiveData - Update/Insert/Delete, skip observer (callback)Android 房间数据库 - LiveData - 更新/插入/删除,跳过观察者(回调)
【发布时间】:2018-10-08 12:56:10
【问题描述】:

我是房间数据库的新手,最近我遇到了一个问题,即修改应用程序的数据库(更新/插入/删除)而不导致观察者中的回调被触发。

这是我的模型的 Dao 类:

@Dao
interface ReceiptRowDao {

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

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

我的Database 班级:

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

    abstract fun myModelDao(): MyModelDao
}

用法:

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

MyClass 中,更新指令将导致无限循环,因为对 MyModel 的更新会触发观察者。然后观察者内部的代码将再次运行。这将进行另一次更新。这将再次触发观察者,依此类推......

在这种情况下,有没有办法更新模型,但跳过可能正在监听变化的观察者?

【问题讨论】:

  • 我已经在 java 文件中实现了这个。我可以分享java代码吗?
  • @Raza 当然,不客气。
  • 当时为什么要update?在您的示例中编写代码的方式保证了更新不会改变项目的任何内容。您需要将该调用设为有条件的,仅在需要更新时使用 update,在这种情况下,更新版本第二次访问您的观察者时,它不应再次调用 update
  • @zapl 应该是更新前修改了一些属性。我认为这很明显,但我要编辑我的问题。谢谢。
  • @DionisBeqiraj 只是想确认您是否在这里使用了两个不同的实体,因为 getMyModels 是 MyModel 并且更新是 ReceiptRow ?那么他们将如何在循环中修复?你运行代码了吗?

标签: android database kotlin android-room android-database


【解决方案1】:

我认为您可以做的只是检查data 是否已经在数据库中。喜欢

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

【讨论】:

  • 由于这是一个更新,这意味着update 操作甚至可以在现有元素上执行。在这种情况下,我不希望观察者被解雇。
  • @DionisBeqiraj 然后您可以检查数据是否已经更新?无论如何...这是一个短路解决方案。你可以使用SingleLiveEvent 并观察这个而不是myLiveData 吗?
【解决方案2】:

这是包含 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();
}
}

你想在数据库中插入数据的部分有两个参数。一个数据库类对象和实体。我将实体类设计为模型类,您可以使用它在主类中设置和获取值。

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

而setDailyDatabase方法只是调用数据库类插入实体

  private void setDailyDataBase(MyDataBase dataBase, DailyConsumption dailyConsumption) {

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

【讨论】:

  • 我认为这不能回答我的问题。我需要在 Observer 中执行 update ,该 Observer 正在侦听发生更新的同一模型中的更改。我在您的代码中没有看到任何观察者。
【解决方案3】:

对于您的问题,我建议您按照以下方式观察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)
}
}

这将帮助您将 观察者逻辑更新逻辑 分开,现在在您想要观察数据的地方调用 getDataObserver() 方法并在您使用 test() 方法时想要更新你的模型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    相关资源
    最近更新 更多