简体   繁体   中英

Android - Room pre-populate database doubts

I have to Pre-populate a Room database on the first run, and I saw that Florina Muntenescu gist about it.

https://gist.github.com/florina-muntenescu/697e543652b03d3d2a06703f5d6b44b5#pre-populate-a-room-database

So, there we have...

   @Database(entities = arrayOf(Data::class), version = 1)
   abstract class DataDatabase : RoomDatabase() {

   abstract fun dataDao(): DataDao

  companion object {

    @Volatile private var INSTANCE: DataDatabase? = null

    fun getInstance(context: Context): DataDatabase =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
            }

    private fun buildDatabase(context: Context) =
            Room.databaseBuilder(context.applicationContext,
                    DataDatabase::class.java, "Sample.db")
                    // prepopulate the database after onCreate was called
                    .addCallback(object : Callback() {
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                            // insert the data on the IO Thread
                            ioThread {
                                getInstance(context).dataDao().insertData(PREPOPULATE_DATA)
                            }
                        }
                    })
                    .build()

    val PREPOPULATE_DATA = listOf(Data("1", "val"), Data("2", "val 2"))
  }

But I don't get it where should I call this getInstance method, do I need to make some dummy DAO call (just to populate DB) in my fragments, MainActivity or elsewhere? (Let's say that I'm planing to use MVVM in this project).

Or maybe I'm just to tired and blind to see solution...

I'm not 100% sure I understand what your end goal is; however, when I am writing applications that use SQLite database, I like to have some dummy information that I can add to the database immediately so I can see how all my different activities will respond to queries and such.

On my main screen, I usually put a button that says "Add Dummy Data". OnClick, it calls the function addDummyData() from my SQLHelper class to write the 20 or so insert statements. Once I have my app up and running the way I want it, I will delete the button before distributing it.

If you add your insert statements to be called automatically (ie without some user intervention of pressing a button, selecting a menu item, etc.), then you run the risk of your app adding those same 20 insert lines every time the app starts up. Your database will get overwhelmed with multiple duplicates pretty quickly. You would need to add an if{} statement that first checks to see if the data already exists in the database (for instance, run a query with a return cursor for one of the dummy values and if the cursor count is zero, then proceed with populating the database, or else don't).

To me, there are 5 steps in creating a creating and access a database with ROOM.

1) Setup Entity, is your name object(each entry in the database).


    @Entity(tableName = "my_table")
    public class MyEntity {
         @PrimaryKey(autoGenerate = true)
         private int mId;

         private String mFirstName;
         private String mLastName;
         public MyEntity(String firstName, String lastName) {
             this.mFirstName = firstName;
             this.mLastName = lastName;
         }
        public int getId() {
            return mId;
        }

        public String getFirstName() {
            return mFirstName;
        }

        public String getLastName() {
            return mLastName;
        }

        public void setId(int mId) {
            this.mId = mId;
        }
    }

2) Setup DAO, the DAO is how you communicate with the databases.

@Dao
public interface MyDao {
    @Query("SELECT * FROM my_table")
    LiveData<List<MyEntity>> getAllNames();

    @Inster
     void insert(MyEntity name);

3) Setup Database

@DataBase(entities = {MyEntity.class}, version 1, exportschema = false}
public abastract class MyDatabase extends RoomDatabase {
    private static MyDatabase INSTANCE;
    public MyDao mMyDao;

    public static synchronized MyDatabase getInstance(Context context) {
        if(INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                MyDatabase.class "database_name")
                .fallbackToDestructiveMigration()
                .addCallback(roomCallBack)
                .build();
        }
        return INSTANCE;

    private static RoomDatabase.Callback roomCallBack = new RoomDatabase.Callback() {
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            new PopulateDbAsyncTask(INSTANCE).execute();
        }
    };
}

private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
        private MyDao mMyDao;

        public PopulateDbAsyncTask(MyDatabase db) {
            this.mMyDao = db.MyDao();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            mMyDao.insert(new MyEntity("FirstName", "LastName")
            // Repeat as many times as needed.
            return null;
        }
    }

4) Setup Repository, Repository calls/Creates the Database

public class MyRepository {

    private MyDao mMyDao;
    private LiveData<List<MyEntity>> mMyList;

    // Constructor will call the database Class.
    public MyRepository(Application application) {
        MyDatabase db = MyDatabase.getInstance(application);
        this.mMyDao = db.mMyDao;
        mMyList = mMyDao.getAllNames();
    }

    public LiveData<List<MyEntity> getAllNames() {
        return mMyList;
    }
}

5) Setup View Model, access your ViewModel from the activity or fragment.

public class MyViewModel extends ViewModel {
    private LiveData<List<MyEntity>> mMyList;
    private Repository mRepository;    

    public MyViewModel(Application application) {
        this.mApplication = application;
        mRepository = new Repository(application);
        this.mMyList = mRepository.getAllNames;
    }

    public LiveData<List<MyEntity>> getAllNames() {
        return mMyList = mRepository.getAllNames();
    }

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