Skip to content Skip to sidebar Skip to footer

Room Database: Getting Select Max() Twice After Creating New Recyclerview Item

I have a RecyclerView list of CardView items that is working properly. Upon creation of a new CardView that is inserted into the database, I would like to fire a Toast that inform

Solution 1:

The view model operations you call within onClickSave are asynchronous:

publicvoidonClickSave(View v){
    mViewModel.insertCard(card1);
    mViewModel.getMax().observe(this, value -> { newMax = value; makeText(AddorUpdateCardActivity.this, "TEXT", .LENGTH_LONG).show();});
}

The implementation of LiveData records the data version as well as the last version seen by the observer.

Therefore insertCard starts to operate on a worker thread while you start observing getMax from the main thread with a newly created observer. Thus you'll receive the current value as well as the new value after the database was updated.

Instead you could observe it only once in onCreate() and wait for the updates triggered by the database:

@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mViewModel = newViewModelProvider(this).get(cardViewModel.class);
    mViewModel.getMax().observe(this, value -> { newMax = value; makeText(AddorUpdateCardActivity.this, "TEXT", .LENGTH_LONG).show();});
}

publicvoidonClickSave(View v) {
    mViewModel.insertCard(card1);
}

Solution 2:

The Room Insert operation inside AsyncTask takes a while before the maxCount variable is updated. Since you are showing the Toast inside a button click, the message is displayed right away without receiving the updated value from LiveData.

Move the Toast message inside the obverve() method so that it gets triggered only after a LiveData change.

mViewModel.getMax().observe(this, value -> {
        newMax = value;
        Toast.makeText(AddorUpdateCardActivity.this, "card #" + newMax + " was saved to the list", Toast.LENGTH_LONG).show();
    });

At this point, the code should be working but you'll get multiple LiveData events for a single Insert. This is happening because you have used 2 separate instances of Dao for Insert and Query operation.

publiccardRepository(Application application) {
    RoomDatabase db = RoomDatabase.getDatabase(application);
    cardDao = db.cardDao(); // <---------- Instance #1
    getMax = cardDao.getMax();
}

publicLiveData<Integer> getMax() {
    return getMax;  
}

 publicvoidinsertCard(Card newcard) {
    newInsertAsyncTask(quickcardDao).execute(newcard);
}

privatestaticclassInsertAsyncTaskextendsAsyncTask<Card, Void, Integer> {

    privateCardDao asyncTaskDao;

    InsertAsyncTask(CardDao dao) {
        asyncTaskDao = dao; // <---------- Instance #2
    }

    @OverrideprotectedIntegerdoInBackground(final Card... params) {

        asyncTaskDao.insertCard(params[0]);
        returnnull;
    }
}

To resolve it use the same Dao instance everywhere:

publiccardRepository(Application application) {
        RoomDatabase db = RoomDatabase.getDatabase(application);
        cardDao = db.cardDao();
    }

    publicLiveData<Integer> getMax() {
        return cardDao.getMax();  
    }

     publicvoidinsertCard(Card newcard) {
        AsyncTask.execute(() -> cardDao.insertCard(newcard));
    }

Solution 3:

Because of using AsyncTask to insert card to database, that function take some time to complete and you show your toast, instantly! Change your activity to this:

AddorUpdateCardActivity
...
privateint newMax = -1;

@Override
protectedvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mViewModel = new ViewModelProvider(this).get(cardViewModel.class);

    mViewModel.getMax().observe(this, integer2 -> {
        newMax = integer2;
        Toast.makeText(AddorUpdateCardActivity.this, "card #" + newMax + " was saved to the list", Toast.LENGTH_LONG).show();
        hideProgressBar();
    });
}

publicvoidonClickSave(View v) {

    //set card data// then insert data in database
    mViewModel.insertCard(card1);

    showProgressBar();
}

Post a Comment for "Room Database: Getting Select Max() Twice After Creating New Recyclerview Item"