Search code examples
javaandroidandroid-sqliteandroid-room

Fetch recently inserted row id using Room library


I'm using room persistence library to update the database. I'm stuck at a point where I want to fetch the id of recently inserted record.

I know that using long as the return type for the insert method returns the id. But I access this Dao method through a viewmodel.

My DAO method is as follows:

//MyDao
@Insert
long insert(RecordItem record);

This method is accessed from a repository by doing this:

//MyRepository
public class MyRepository {
    private MyDao myDao;

    public MyRepository(@NonNull Application application) {
        MainDatabase mainDatabase = MainDatabase.getInstance(application);
        myDao = mainDatabase.myDao();
    }

    public void insert(RecordItem record) {
        MainDatabase.dbWriteExecutor.execute(() -> {
            myDao.insert(record);
        });
    }
}

And the repository method is called from viewmodel as follows:

//MyViewModel
public void insert(RecordItem record) {
    repository.insert(record);
}

And finally the viewmodel method as:

//MyActivity
myViewModel.insert(record);

My problem is, I don't know how I can get long returned through a viewmodel method. I tried doing this in repository

//MyRepository
public class MyRepository {
    private MyDao myDao;
    private long id;

    public MyRepository(@NonNull Application application) {
        MainDatabase mainDatabase = MainDatabase.getInstance(application);
        myDao = mainDatabase.myDao();
    }

    public long insert(RecordItem record) {
        MainDatabase.dbWriteExecutor.execute(() -> {
            id = myDao.insert(record);
        });
        return id;
    }
}

and subsequent changes to viewmodel method as well.

However, it returns 0, which I suppose happens since the insert method is executed on a different thread and id is returned as soon as the statement is reached(correct me if I'm wrong).

Thanks in advance.


Solution

  • You can approach following solution for your issue:

    Create a Callback interface as below:

    public interface DbInsertCallback {
        void onInsert(long insertedItemId);
    }
    

    Then use this interface on your repository insert(RecordItem record) method like below usage:

    public class MyRepository {
        
        // ... Some repo code ...
    
        public void insert(RecordItem record, DbInsertCallback callback) {
            MainDatabase.dbWriteExecutor.execute(() -> {
                long id = myDao.insert(record);
                callback.onInsert(id);
            });
        }
    
        // ... Rest of repo code ...
    }
    

    And also make necessary changes on caller site (I.e. ViewModel & Activity) to provide object of this callback class as parameter as well. To do the implementation of this interface, you can either create object of that interface along with implementation or else pass it contextually like providing this.