Im trying to learn android at present and im building an app with a database - ive used Room, but cant seem to get the database inspector to show me my tables or confirm they exist! I have 4 entities and 4 DAOs. I dont get an app crash, i just cant see my database in the database inspector. I was trying to check the database via the inspector first before finalising all LiveData and logic for the app as the db is the foundation.
Ive built the android codelab, and crosschecked my Room architecture vs the code lab. Ive downloaded and ran the same codelab and im able to inspect its Database no problem. Ive invalidated caches and restarted as well.
When i use the "ViewModelProvider" inside the main activity onCreate() to link the main activity to the ViewModel, is it bypassing my constructor - it doesn't seem to be as im getting logging statements out of the constructor...
When ive refactored anything for Room, ive went to build > clean then build > rebuild.
Ive added logging statements through from the main activity (single activity app) > viewmodel > repository > database class - and all logs are being returned, so the code is calling in the correct sequence.
When i attempt to load the database inspector i see the following;
Android Studio Database Inspector View
Here is the code from the UI "down" - Starting with main Activity;
public class MainActivity extends AppCompatActivity {
private ViewModelTimerSetup viewModelTimerSetup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Log.d(ViewModelTimerSetup.getStaticLogTag(), "Main Activity - just before calling viewmodel");
// generate a setupViewModel and therefore the db (vm > repository > db).
viewModelTimerSetup = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory
.getInstance(this.getApplication())).get(ViewModelTimerSetup.class);
Log.d(ViewModelTimerSetup.getStaticLogTag(), "Main Activity - just after calling viewmodel");
ViewModel;
public class ViewModelTimerSetup extends AndroidViewModel {
public static String getStaticLogTag() {
return STATIC_LOG_TAG;
}
private static final String STATIC_LOG_TAG = "my_logging";
private final LiveData> allTimerDesigns;
private final LiveData> allTimerRecords;
// instantiate the app repository to access the database
private AppRepository appRepository;
/**
* system required constructor, also gets the DBs from the app repository
* @param application
*/
public ViewModelTimerSetup(@NonNull Application application) {
super(application);
Log.d(STATIC_LOG_TAG, "Log tag - inside ViewModelTimerSetup constructor - pre making new db");
// instantiate the access to the repository for db access
appRepository = new AppRepository(application);
Log.d(STATIC_LOG_TAG, "Log tag - inside the ViewModelTimerSetup constructor - after making new db");
allTimerDesigns = appRepository.getAllTimerDesigns();
allTimerRecords = appRepository.getAllTimerRecords();
}
Repository Constructor;
public AppRepository(Application application) {
// find the db and if it doesnt exist, build one
Log.d(ViewModelTimerSetup.getStaticLogTag(), "Repository - just before calling new database instance");
AllTimersDatabase allTimersDatabase = AllTimersDatabase.getDatabase(application);
Log.d(ViewModelTimerSetup.getStaticLogTag(), "Repository - just after calling new database instance");
// instantiate all DAOs
intervalDesignDAO = allTimersDatabase.intervalDesignDAO();
intervalRecordsDAO = allTimersDatabase.intervalRecordsDAO();
timerDesignDAO = allTimersDatabase.timerDesignDAO();
timerRecordsDAO = allTimersDatabase.timerRecordsDAO();
}
Here is the database class (myDatabaseCallback omitted for brevity).
@Database(entities = {TimerDesign.class, TimerRecords.class,
IntervalDesign.class, IntervalRecord.class}, version = 1)
public abstract class AllTimersDatabase extends RoomDatabase {
// generate a single instance of the full allTimersDatabase
private static volatile AllTimersDatabase allTimersDatabaseInstance;
// build an executor service with 4 threads for background queries
private static final int NUMBER_OF_THREADS = 4;
static final ExecutorService databaseWriteExecutor =
Executors.newFixedThreadPool(NUMBER_OF_THREADS);
// instantiate the DAOs
public abstract IntervalDesignDAO intervalDesignDAO();
public abstract IntervalRecordsDAO intervalRecordsDAO();
public abstract TimerDesignDAO timerDesignDAO();
public abstract TimerRecordsDAO timerRecordsDAO();
/**
* get one instance of the full db,
* otherwise if no db exists, generate one
* @param context
* @return a full allTimersDatabase
*/
public static AllTimersDatabase getDatabase(Context context) {
if (allTimersDatabaseInstance == null) {
synchronized (AllTimersDatabase.class) {
if (allTimersDatabaseInstance == null) {
Log.d(ViewModelTimerSetup.getStaticLogTag(), "Database - before building new database instance");
allTimersDatabaseInstance = Room.databaseBuilder(context.getApplicationContext(),
AllTimersDatabase.class, "timers_database")
.fallbackToDestructiveMigration()
.addCallback(myDatabaseCallback)
.build();
}
}
}
Log.d(ViewModelTimerSetup.getStaticLogTag(), allTimersDatabaseInstance.toString());
return allTimersDatabaseInstance;
}
A example entity - all entities are built with appropriate Room annotations, getters, setters and 1 constructor
@Entity(tableName = "timer_design")
public class TimerDesign {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "timer_design_id")
private int timerDesignID;
@ColumnInfo(name = "timer_name")
@NonNull
private String timerName;
@ColumnInfo(name = "total_duration", defaultValue = "00:00:00")
@NonNull
private String totalDuration;
/**
* constructor excl the id (id is autogenerated).
* @param timerName
*/
public TimerDesign(String timerName) {
this.timerName = timerName;
totalDuration = "00:00:00";
}
/**
* setter for the ID
* @param timerDesignID
*/
public void setTimerDesignID(int timerDesignID) {
this.timerDesignID = timerDesignID;
}
/**
* getter for the id
* @return
*/
public int getTimerDesignID() {
return timerDesignID;
}
/**
* getter for the timer name
* @return
*/
public String getTimerName() {
return timerName;
}
/**
* setter for the timer name
* @param timerName
*/
public void setTimerName(@NonNull String timerName) {
this.timerName = timerName;
}
/**
* getter for the total duration
* @return
*/
@NonNull
public String getTotalDuration() {
return totalDuration;
}
/**
* setter for the total duration
* @param totalDuration
*/
public void setTotalDuration(@NonNull String totalDuration) {
this.totalDuration = totalDuration;
}
}
And the DAO for the Entity above;
@Dao
public interface TimerDesignDAO {
// https://developer.android.com/reference/androidx/room/OnConflictStrategy.html
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(TimerDesign timerDesign);
@Update
void update(TimerDesign timerDesign);
@Delete
void delete(TimerDesign timerDesign);
// delete all timers
@Query("DELETE FROM timer_design")
void deleteAllTimerDesigns();
// get a list of all designed timers
@Query("SELECT * FROM timer_design")
LiveData> getAllTimerDesigns();
// get a single timer design
@Query("SELECT * FROM timer_design WHERE timer_design_id = :timerID")
LiveData> getOneTimerDesign(int timerID);
// get the id of the most recently inserted timer
@Query("SELECT MAX(timer_design_id) FROM timer_design")
int getMostRecentInsertedTimerID();
}
... and lastly my logcat log showing only "my_logging" key. In frustration ive asked for a log of the object name of the database instance .toString() to see if an object is being created at all.
2021-05-12 15:02:37.798 xxx D/my_logging: Main Activity - just before calling viewmodel
2021-05-12 15:02:37.799 xxx D/my_logging: Log tag - inside ViewModelTimerSetup constructor - pre making new db
2021-05-12 15:02:37.803 xxx D/my_logging: Repository - just before calling new database instance
2021-05-12 15:02:37.811 xxx D/my_logging: Database - before building new database instance
2021-05-12 15:02:37.841 xxx D/my_logging: xxx.AllTimersDatabase_Impl@cf67ddc
2021-05-12 15:02:37.841 xxx D/my_logging: Repository - just after calling new database instance
2021-05-12 15:02:37.862 xxx D/my_logging: Log tag - inside the ViewModelTimerSetup constructor - after making new db
2021-05-12 15:02:37.865 xxx D/my_logging: Main Activity - just after calling viewmodel
2021-05-12 15:02:38.349 xxx D/my_logging: Log tag - inside ViewModelTimerSetup constructor - pre making new db
2021-05-12 15:02:38.349 xxx D/my_logging: Repository - just before calling new database instance
2021-05-12 15:02:38.349 xxx D/my_logging: xxx.AllTimersDatabase_Impl@cf67ddc
2021-05-12 15:02:38.350 xxx D/my_logging: Repository - just after calling new database instance
2021-05-12 15:02:38.350 xxx D/my_logging: Log tag - inside the ViewModelTimerSetup constructor - after making new db