简体   繁体   中英

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.

This is the Dao class for my model:

@Dao
interface ReceiptRowDao {

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

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

My Database class:

@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. 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. 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

@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

  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 :

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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