Android Room : LiveData callback of update insert?

android room update not working
android-room insert or update
android room transaction
android-room insert return id
android room multiple databases
android room query
android-room check if record exists
android-room livedata not updating

I have a Simple DAO including CRUD function

FeedEntryDAO.java

@Dao
public interface FeedEntryDAO {

  @Query("SELECT * FROM feedEntrys")
  LiveData<List<FeedEntry>> getAll();

  @Query("SELECT * FROM feedEntrys WHERE uid = :uid LIMIT 1")
  LiveData<FeedEntry> findByUid(int uid);

  @Insert
  void insertAll(FeedEntry... feedEntries);

  @Delete
  void delete(FeedEntry feedEntry);

  @Update
  int update(FeedEntry feedEntry);

}

For the select , it is okay to return the LiveData type.

Inside the Activity the code is pretty for the selection

viewModel.getFeedEntrys().observe(this,entries -> {...});

However, when I try to insert, update , delete the data. The code seems a little bit ugly and also create a asynctask every time.

new AsyncTask<FeedEntry, Void, Void>() {
                @Override
                protected Void doInBackground(FeedEntry... feedEntries) {
                  viewModel.update(feedEntries[0]);
                  return null;
                }
}.execute(feedEntry);

I have 2 question about it:

  1. Can I use LiveData to wrap the delete, insert , update function ?
  2. Better way to maintain such asynctask class for delete, insert , update?

Appreciate any suggestions and advices. Thank you.


  1. Can i use LiveData to wrap Delete, Insert, Update calls?

No, you can't. I wrote an answer to the issue. The reason is, that LiveData is used to notify for changes. Insert, Update, Delete won't trigger a change. It will return the deleted rows, the inserted ID or the affected rows. Even if it looks horrible it makes sense not having LiveData wrapped around your stuff. Anyway, it would make sense to have something like Single around the calls to let the operation triggered and operated on a RX-Java operation.

If you want to trigger those calls, you observe on a selection query which notify your LiveData onec you have updated, inserted or deleted some/any data.

  1. Better way to maintain such asynctask class for delete, insert , update?

After looking at your example it looks like that you misuse the (Model/View/)ViewModel-Pattern. You should never access your repository in your view. I'm not sure if you'r doing this because its not visible in your sample. Anyway, after observing your LiveData and getting a result, there's no need to wrap the updating of data inside your viewModel in an AsyncTask. That means, that you should alway take care of

a) view <-> viewmodel <-> repository and not view <-> repository and view <-> viewmodel

and

b) don't try to use threads which are not needed. You observe LiveData on a Background Thread (@WorkerThread) by default (if not annotated with @MainThread) and get the value in the ui-thread (@MainThread).

Android Room : LiveData callback of update insert?, Can i use LiveData to wrap Delete, Insert, Update calls? No, you can't. I wrote an answer to the issue. The reason is, that LiveData is used to notify for changes. The related concept documentation is in 10.1: Room, LiveData, and ViewModel. To continue working with the RoomWordsSample app and learn more ways to use a Room database, see the 10.1 Part B: Room, LiveData, and ViewModel codelab, which takes up where this codelab leaves off. Android developer documentation: Guide to App Architecture


For the second question, there is another neater alternative to AsyncTask; which is using java Executor, the good news is that you can use a single instance of Executor instead of multiple instances of the AsyncTask for all CRUD operations.

Demo Example

public class Repository {

    private static Repository instance;
    private MyDatabase mDatabase;
    private Executor mExecutor = Executors.newSingleThreadExecutor();

    private Repository(Application application) {
        mDatabase = MyDatabase.getInstance(application.getApplicationContext());
    }

    public static Repository getInstance(Application application) {
        if (instance == null) {
            instance = new Repository(application);
        }
        return instance;
    }


    public void insert(final MyModel model) {

        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().insert(model);
            }
        });
    }

    public void update(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().update(model);
            }
        });
    }

    public void delete(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().delete(model);
            }
        });
    }

}

7 Pro-tips for Room - Android Developers, Room is an abstraction layer on top of SQLite that makes it easier and nicer to persist data. Pre-populate your database via RoomDatabase#Callback; Use and find yourself copying the same Insert , Update and Delete methods? fun getUserById(id: String): LiveData<User>// or@Query(“SELECT  LiveData is an observable data holder, part of the Android Jetpack. Here is the video from Android Developers Channel: LiveData is an observable data holder class.


Concerning question 2:

For Kotlin users there is now a really nice way to achieve this, because since Room 2.1 there is direct support for coroutines. A neat example is given here.

You can use a "suspend function" directly in the DAO, which takes care that nothing is executed on the main thread:

@Dao
 interface BarDao {

   @Query("SELECT * FROM bar WHERE groupId = 2")
   fun getAllBars(): LiveData<MutableList<Bar>>

   @Query( "SELECT * FROM bar WHERE groupId = 0 LIMIT 1")
   fun getRecentBar(): LiveData<Bar>

   @Insert
   suspend fun insert(bar: Bar)

   @Update
   suspend fun update(bar: Bar)

   @Delete
   suspend fun delete(bar: Bar)

}

then in your viewModel you would just:

    fun insert(bar: Bar) = viewModelScope.launch {
        barDao.insert(bar)
    }

    fun update(bar: Bar) = viewModelScope.launch {
        barDao.update(bar)
    }

    fun delete(bar: Bar)= viewModelScope.launch {
        barDao.delete(bar)
    }

14.1A: Room, LiveData, ViewModel · GitBook, 14.1A: Working with Architecture Components: Room, LiveData, ViewModel The Android operating system provides a strong foundation for building apps that Add a Room database to the app for persisting data locally, and initialize the database. Update your Word class with annotations, as shown in the code below. LiveData, a lifecycle library class for data observation, solves this problem. Use a return value of type LiveData in your method description, and Room generates all necessary code to update the LiveData when the database is updated. Note: If you use LiveData independently from Room, you have to manage updating the data.


You can use @Dao annotation in abstract classes too, so:

  1. Create an abstract @Dao BaseDao class with the abstract methods @Insert insert(entities) and with the concrete method insert(entities, callback) that do that ugly AsyncTask job, calling the abstract @Insert insert(entities) on onBackground and your callback on onPostExecute.
  2. Make your FeedEntryDAO also abstract extend BaseDao and the @Query methods abstract.

The result usage in Kotlin is quite pretty:

database.entityDao().insert(entities) { ids ->
    // success
}

14.1B: Deleting and updating data with Room · GitBook, You should be able to create and run apps in Android Studio 3.0 or higher. You learned these topics in the previous practical, 15.1A: Working with Architecture Components: Room, LiveData, ViewModel. Then you add a menu item that allows the user to delete all the data. SimpleCallback(0, ItemTouchHelper. Notice that the load method returns an object of type LiveData<User>. Room knows when the database is modified and automatically notifies all active observers when the data changes. Because Room uses LiveData, this operation is efficient; it updates the data only when there is at least one active observer.


To Address your 2nd Question:

Google has posted an Android Room Codelab here which has laid out a concise MVVM architecture for implementing Room in Android:

Here the recommendation is to have database operations handled by a public static ExecutorService within the Database class. The location of the ExecutorService class can vary, just remember the idea is in MVVM your view does not care about how data are actually CURD'ed, that's the responsibility of the ViewModel, not View.

github repository for this code lab

In short, to apply a similar idea to your code, it would be something like this:

class YourRepository {
    private FeedEntryDAO mFeedEntryDAO;

    YourRepository(Application application) {
        YourDatabase db = YourDatabase.getDatabase(application);
        mFeedEntryDAO = db.feedEntryDAO();
        mAllWords = mWordDao.getAlphabetizedWords();
    }


    void update(FeedEntry feedEntry) {
        Database.databaseExecutor.execute(() - > {
            mFeedEntryDAO.update(feedEntry);
        });
    }
}

class YourViewModel extends ViewModel {
    private YourRepository mRepository;
    void update(FeedEntry feedEntry) {
        mRepository.update(feedEntry)
    }
}

By doing this, your View can directly call viewModel.update(feedEntries[0]).

One important thing to mention is the mFeedEntryDAO.update(feedEntry) will automatically trigger the onChanged callback of your observer on the getFeedEntrys LiveData.

This is quite handy in your case. You can read more about how the trigger happens here.

Android Room Database - LiveData, Android Room Database - LiveData - Update/Insert/Delete, skip observer (​callback). android room, livedata example java android room update room livedata  android.arch.persistence.room.Insert Marks a method in a Dao annotated class as an insert method. The implementation of the method will insert its parameters into the database.


Room Insert, This practical codelab is part of Unit 4: Saving user data in the Android a ViewModel that serves LiveData , a Repository, and a Room database. changes its state, all the object's dependents are notified and updated automatically. Add a Room database to the app for persisting data locally, and initialize the database. Android; Android Room Insert or Update December 27, 2018. android room Perform insert if new, else perform update Solution 1. Try insert first. LiveData and Room)


Android fundamentals 10.1 Part A: Room, LiveData, and ViewModel, In this tutorial, you'll learn how to use coroutines with the Room persistence to build Android applications, work with the Room persistence library and use the Ideally, you want to insert the data while the database is being created. Time to launch a coroutine from your callback to do some heavy lifting. The target entity of the update method. When this is declared, the update method parameters are interpreted as partial entities when the type of the parameter differs from the target. The POJO class that represents the entity must contain a subset of the fields of the target entity along with its primary keys.


Coroutines With Room Persistence Library, That “operation” is not any kind of callback that we can handle and do some Tracker creates trigger for any update, insert or delete for a given  Android Persistence codelab (LiveData, Room, DAO) Android lifecycle-aware components codelab (ViewModel, LiveData, LifecycleOwner, LifecycleRegistryOwner) Android Room with a View (same code as this practical) Videos: Architecture Components overview; Architecture Components: LiveData and Lifecycle; Architecture Components: ViewModel; Code samples: