Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm working on an app that uses
Room
database; it's a static database that has 3 tables that I insert their data at the first time the app launches by overriding
onCreate()
upon database instantiation.
It takes a while until inserting all the static records to the three tables, so my app can't access database until the
onCreate()
is over to get the right data back to be shown to the user.
When I try to access the database within the activity's
onCreate()
method, it returns
null
data, and this literally interrupts the Room's
onCreate
operation, which lead to null data for upcoming launches of the app as the Room's
onCreate()
is called only once.
For debugging purpose, when I get rid of this database access only for the first time launch of the app (after clean uninstall) to allow the database to build-up for the first launch; then when I re-add the database query to my activity's
onCreate()
and relaunch the app; it returns non-null data; I just wanted to make sure that Room's
onCreate()
is over of the 1st launch.
I can pass a listener to the custom Room RoomDatabase class where its callback can be triggered upon the end of
onCreate()
method; but I'm not sure if this is the right way to do this or there is another elegant way, and if this is the right way; then how to implement it the right way taking the MVVM design pattern, stuff like
Repository
,
ViewModel
into consideration.
Here's how the database class looks like
@Database(entities = {Table1.class, Table2.class, Table3.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "database.db";
private static volatile AppDatabase INSTANCE;
private static final Object LOCK = new Object();
public abstract Table1Dao getTable1Dao();
public abstract Table2Dao getTable2Dao();
public abstract Table2Dao getTable3Dao();
private static Executor mExecutor = Executors.newSingleThreadExecutor();
static public AppDatabase getInstance(final Context context) {
if (INSTANCE == null) {
synchronized (LOCK) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DATABASE_NAME)
.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
mExecutor.execute(() -> table1InsertOperation(context));
mExecutor.execute(() -> table2InsertOperation(context));
mExecutor.execute(() -> table3InsertOperation(context));
super.onCreate(db);
.build();
return INSTANCE;
Do appreciate your help
"When I try to access the database within the activity's onCreate() method, it returns null data, and this literally interrupts the Room's onCreate operation, which lead to null data for upcoming launches of the app as the Room's onCreate() is called only once."
This seems pretty weird to me, a db is made to allow multiple threads to read and write, so why that should happen?
"I can pass a listener to the custom Room RoomDatabase class where its callback can be triggered upon the end of onCreate() method" I see you use an Executor to run the population phase on background threads, so onCreate should finish almost immediately, the threads that populate the db most probably much later. You would have to monitor when all the three threads you run all finish their work.
Same as the listener, but much easier (once you solve point 1 that seems a bug somewhere in your code or less probably in Room) would be just to have a LiveData (or Flow) that tells you when all the rows are inserted.
Look at this repo: https://gist.github.com/florina-muntenescu/697e543652b03d3d2a06703f5d6b44b5
she uses an Executors.newSingleThreadExecutor()
and seems similar to what you do
Ps. Android Studio 4.1 has an amazing Database Inspector, try it!
–
–
–
–
Use a development version of your app or other tool (e.g. sqlite3) to create a database file containing your fixed data. Place the DB file in your app's assets/
directory and use it to prepopulate your database.
See the docs for createFromAsset() for details.
The think the resulting app database will be ready for use immediately after returning from RoomDatabase.build(). You could also use the onOpen() callback.
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.