androidandroid-roomandroid-livedataandroid-jetpackandroid-guava

Problem in adding Room for data storage in android using java


I was trying to implement Room for persistent data storage in java. But I ran into problems with it.

In first try:

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addUser(UserDetails userDetails);

}

MyDatabase.java

@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {

    public abstract MyDao myDao();
}

with the above the app crashes with error:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
whenever I try to insert a data into the database.

In the second try:

MyDao.java

@Dao
public interface MyDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    ListenableFuture<Integer> addUser(UserDetails userDetails);

}

MyDatabase.java

@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {

    public abstract MyDao myDao();
}

changed the return type to hold ListenableFuture<Integer> because official doc says to do so. The app does not build successfully and shows the following error:
error: Not sure how to handle insert method's return type.

So, my question is how can I correctly and successfully insert data in the database using room with java.
Please help.


Solution

  • After wandering on the internet for ages, I came to know that it is possible to write insert query using following 2 methods:

    1. Using a thread class

    Operations.java

    public class Operations{
    
        private MyDao myDao;
    
        public Operations(Context context){
            MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
                    .fallbackToDestructiveMigration()
                    .build();
            myDao = db.myDao();
        }
    
        public void insertUser(UserDetails userDetails){
            new Thread{
                @override
                public void run(){
                    myDao.addUser(userDetails);
                }
            }.start();
        }
    
    }
    

    MyDao.java

    @Dao
    public interface MyDao {
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        void addUser(UserDetails userDetails);
    
    }
    

    MyDatabase.java

    @Database(entities = {User.class}, version = 1)
    public abstract class MyDatabase extends RoomDatabase {
    
        public abstract MyDao myDao();
    }
    

    OR

    1. Using ExecutorService class

    Operations.java

    public class Operations{
    
        private MyDao myDao;
    
        public Operations(Context context){
            MyDatabase db = Room.databaseBuilder(context, MyDatabase.class, "database")
                    .fallbackToDestructiveMigration()
                    .build();
            myDao = db.myDao();
        }
    
        public void insertUser(UserDetails userDetails){
            MyDatabase.databaseWriteExecutor.execute(()->{
                   notesDb.notesDao().addNote(note));
               }
        }
    
    }
    

    MyDao.java

    @Dao
    public interface MyDao {
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        void addUser(UserDetails userDetails);
    
    }
    

    MyDatabase.java

    @Database(entities = {User.class}, version = 1)
    public abstract class MyDatabase extends RoomDatabase {
        
        public static final ExecutorService databaseWriteExecutor =
                Executors.newFixedThreadPool(2);
    
        public abstract MyDao myDao();
    }