Branch: dev-todo-mvp-room
This is a question. Please tell me whether I should post this on Stack Overflow or if this is not relevant as it is still an unfinished sample (dev- branch prefix).
TL;DR: Is the database creation an expensive task (i.e. put that off the main thread) or is it cheap (i.e. do whatever you want)?
_By database creation, I mean the call to Room#databaseBuilder()#build()._
The ToDo app has a singleton class for the Room database:
public static ToDoDatabase getInstance(Context context) {
synchronized (sLock) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
ToDoDatabase.class, "Tasks.db")
.build();
}
return INSTANCE;
}
}
This is used on the main thread when creating activities, for example AddEditTaskActivity#onCreate:
// Create the presenter
mAddEditTaskPresenter = new AddEditTaskPresenter(
taskId,
Injection.provideTasksRepository(getApplicationContext()),
addEditTaskFragment,
shouldLoadDataFromRepo);
And in Injection#provideTasksRepository:
public static TasksRepository provideTasksRepository(@NonNull Context context) {
checkNotNull(context);
ToDoDatabase database = ToDoDatabase.getInstance(context);
return TasksRepository.getInstance(FakeTasksRemoteDataSource.getInstance(),
TasksLocalDataSource.getInstance(new AppExecutors(),
database.taskDao()));
}
I thought that this was a bad practise, as we can see from another sample (android-architecture-components/BasicSample), the app database is not a singleton:
public abstract class AppDatabase extends RoomDatabase {
static final String DATABASE_NAME = "basic-sample-db";
public abstract ProductDao productDao();
public abstract CommentDao commentDao();
}
The BasicSample there uses another class, DatabaseCreator, that will create a MutableLiveData object to make the database creation observable:
private final MutableLiveData<Boolean> mIsDatabaseCreated = new MutableLiveData<>();
...
/** Used to observe when the database initialization is done */
public LiveData<Boolean> isDatabaseCreated() {
return mIsDatabaseCreated;
}
The database creation is done in another thread, here's DatabaseCreator#createDb:
public void createDb(Context context) {
// ...
mIsDatabaseCreated.setValue(false);// Trigger an update to show a loading screen.
new AsyncTask<Context, Void, Void>() {
@Override
protected Void doInBackground(Context... params) {
// ...
AppDatabase db = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DATABASE_NAME).build();
// ...
return null;
}
@Override
protected void onPostExecute(Void ignored) {
// Now on the main thread, notify observers that the db is created and ready.
mIsDatabaseCreated.setValue(true);
}
}.execute(context.getApplicationContext());
}
Then they observe DatabaseCreator#isDatabaseCreated which will trigger the load screen (false) and provide data to the UI (true).
So basically this sample (dev-todo-mvp-room) creates the database on the main thread, and BasicSample (from android-architecture-components) creates an observable which triggers when the off-thread task has created the database.
What is the recommended practise?
The database is built only when the database is accessed for the first time.
The build just creates the configuration for the database so you can call this from the main thread.
Thanks a lot.
Most helpful comment
The database is built only when the database is accessed for the first time.
The build just creates the configuration for the database so you can call this from the main thread.