【发布时间】:2021-05-12 14:21:52
【问题描述】:
我目前正在尝试学习 android,并正在使用数据库构建应用程序 - 我使用过 Room,但似乎无法让数据库检查器向我展示我的表格或确认它们存在!我有 4 个实体和 4 个 DAO。我没有遇到应用程序崩溃,我只是在数据库检查器中看不到我的数据库。在最终确定应用程序的所有 LiveData 和逻辑之前,我试图先通过检查器检查数据库,因为数据库是基础。
我已经构建了 android codelab,并交叉检查了我的 Room 架构与代码实验室。我已经下载并运行了相同的代码实验室,并且我能够检查它的数据库没问题。我已经使缓存失效并重新启动。
当我在主要活动onCreate() 中使用“ViewModelProvider”将主要活动链接到 ViewModel 时,它是否绕过了我的构造函数 - 它似乎不像我从构造函数中获取日志语句.. .
当我为 Room 重构任何东西时,我先构建 > 清理然后构建 > 重建。 我已经从主要活动(单个活动应用程序)> viewmodel > 存储库 > 数据库类添加了日志记录语句 - 并且正在返回所有日志,因此代码以正确的顺序调用。
当我尝试加载数据库检查器时,我看到以下内容; Android Studio Database Inspector View
这是 UI“向下”的代码 - 从主 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");
视图模型;
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<List<TimerDesign>> allTimerDesigns;
private final LiveData<List<TimerRecords>> 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();
}
存储库构造器;
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();
}
这里是数据库类(myDatabaseCallback 为简洁起见省略)。
@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;
}
一个示例实体 - 所有实体都使用适当的 Room 注释、getter、setter 和 1 个构造函数构建
@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;
}
}
以及上述实体的 DAO;
@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<List<TimerDesign>> getAllTimerDesigns();
// get a single timer design
@Query("SELECT * FROM timer_design WHERE timer_design_id = :timerID")
LiveData<List<TimerDesign>> getOneTimerDesign(int timerID);
// get the id of the most recently inserted timer
@Query("SELECT MAX(timer_design_id) FROM timer_design")
int getMostRecentInsertedTimerID();
}
...最后我的 logcat 日志只显示“my_logging”键。沮丧中,我要求记录数据库实例的对象名称 .toString() 以查看是否正在创建对象。
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
【问题讨论】:
-
数据库里还有东西吗?对此不是 100% 确定的,但可能是在您实际添加某些内容之前不会创建数据库
-
嗨 Ivan,我请求将一些对象添加到 RoomDatabase.Callback "myDatabaseCallback" 中的一些表中,但这对数据库检查器没有任何影响。与此同时,我将转到 UI 并查看构建完整 UI 后是否可以像用户一样添加对象,然后我不知道这是 Android Studio 问题还是数据库问题
-
您总是可以尝试通过设备资源管理器查看数据库,它会在
data/data/<the_packagage>/databases/中,您至少会期望timers_database文件,也许还有文件 timers_database-wal 和 timers_database-shm 。如果这些存在,那么它与 Database Inspector 有关。您可以随时复制文件(全部 3 个)并使用 SQLite 工具查看它们。 -
嗨 MikeT,好主意!我怎么没想到!是的,有一个
timers_database文件、一个timers_database_shm和一个timers_database_wal。这三个人都有-rw-rw----的权限,我会按照建议复制它们并检查 -
我认为您的设备至少是 android 8?这是检查员工作所必需的。
标签: android android-studio android-room