我正試圖在Android Studio中使用Room(用Java)創建一個簡單的資料庫。這是為另一個應用程式中的一個插件,所以沒有默認的活動。當我進入Device File Explorer時,資料庫檔案并不存在。我想知道是否有人能給我指出正確的方向?
以下是我創建資料庫的代碼:
public abstract class AppDatabase extends RoomDatabase {
public abstract NoteDao NoteDao()。
private static AppDatabase noteDB;
public static AppDatabase getInstance(Context context) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context);
}
return noteDB。
}
private static AppDatabase buildDatabaseInstance(Context context) {
return Room.databaseBuilder(context,
AppDatabase.class,
"exampleDB")
.allowMainThreadQueries().build()。
}
public void cleanUp(){
noteDB = null;
}
這是我的DAO代碼:
@Dao
public interface NoteDao {
@Query("SELECT * FROM note")
List<Note> getAll()。
@Insert
void insert(Note note)。
@Delete
void delete(Note note)。
@Update
void update(Note note)。
這是我為物體撰寫的代碼:
。@Entity(tableName = "note")
public class Note {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "name")
public String name;
public Note(String name){
this.name = name;
}
public int getId(){
return id。
}
public void setId(int id) {
this.id=id。
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name。
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (! (o instanceof Note) return false;
Note note = (Note)o;
if (id != note.id) return false;
return name != null ? name.equals(note.name) : note.name == null;
}
@Override; }
public int hashCode() {
int result = id;
result = 31 * result (name != null ? name.hashCode() : 0) 。
return result。
}
我正在插件的入口點的onCreate方法中創建資料庫。然而,當我使用下面的函式來檢查資料庫是否存在時,它總是回傳False。
private static String doesDatabaseExist(Context context, String dbName) {
File dbFile = context.getDatabasePath(dbName)。
String path = dbFile.getAbsolutePath() 。
return dbFile.exists()。
當我進入設備檔案資源管理器并搜索應該創建資料庫檔案的路徑時,它并不存在。它也沒有在資料庫檢查器中顯示出來。我看了很多教程&都沒有發現我的代碼有什么問題。Gradle檔案和amp;依賴都是正確的(我遵循Android開發者指南),并且在清單中也添加了權限。
謝謝!
uj5u.com熱心網友回復:
當我進入設備檔案資源管理器并搜索應該創建資料庫檔案的路徑時,它并不存在。
可能的原因(無法確定)是您沒有訪問資料庫(例如,使用其中一個道來添加東西或嘗試檢索東西)。這是因為只有在試圖打開資料庫時才會實際創建資料庫。
與其使用一個道(例如NoteDao.getAll()),不如使用(例如)強制打開:-
private static AppDatabase buildDatabaseInstance(Context context) {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class,
"exampleDB")
.allowMainThreadQueries().build()。
db.getOpenHelper().getWritableDatabase(); //<<<<< 強制開放。
return db;
}
也許可以考慮對你的代碼進行如下調整,這樣就可以打開(最終)2個資料庫(名稱和是否強制打開完全相同)了。
已經添加了回呼,以便在呼叫 onCreate 和 onOpen 時,表示發生的輸出被寫入日志。
因此,修改后的@Database類AppDatabase是:-
@Database(entities = {Note.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract NoteDao NoteDao()。
private static AppDatabase noteDB;
public static final String TAG = "OPENINFO" 。/* 添加 */
/* 不用于演示 */; /* 加入 */
public static AppDatabase getInstance(Context context, String dbName, boolean forceOpen) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context,dbName,forceOpen)。
}
return noteDB。
}
/* made public and added ability to pass dbname and also boolean to force open or not */
public static AppDatabase buildDatabaseInstance(Context context, String dbName, boolean forceOpen) {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class,
dbName)
/* ADDED callbacks to allow open and create to be logged */
.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db)。
Log.d(TAG,"OnCreate callback invoked for " dbName)。
}
@Override。
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db)。
Log.d(TAG,"onOpen callback invoked for " dbName)。
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db)。
}
})
.allowMainThreadQueries().build()。
if (forceOpen) {
db.getOpenHelper().getWritableDatabase()。
}
return db;
}
/* 放在這里是為了讓一切都在一起 */。
/* 稍加修改并公開 */
public static String doesDatabaseExist(Context context, String dbName){
File dbFile = context.getDatabasePath(dbName)。
String path = dbFile.getAbsolutePath() 。
return String.valueOf(dbFile.exists())。
}
/* Will close DB if it is open */
public void cleanUp(){
if (noteDB != null && noteDB.isOpen() ) {
noteDB.close()。
}
noteDB = null;
}
}
在一個活動中使用以下代碼:-
public class MainActivity extends AppCompatActivity {
AppDatabase db1, db2;
NoteDao dao1,dao2。
private static final String db1Name = "example1"。
private static final String db2name = "example2"。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(s savedInstanceState)。
setContentView(R.layout.activity_main)。
/* 第一次運行,那么在這個階段兩個檔案都不應該存在,隨后的運行它們會存在 */
Log.d(AppDatabase.TAG,"File exists for " db1Name " " AppDatabase.doesDatabaseExist(this,db1Name))。
Log.d(AppDatabase.TAG,"File exists for " db2name " " AppDatabase.doesDatabaseExist(this,db2name))。
Log.d(AppDatabase.TAG,"Getting instance for " db1Name " not force opened")。
db1 = AppDatabase.buildDatabaseInstance(this,db1Name,false); /* not force open */
Log.d(AppDatabase.TAG,"Getting instance for " db2name " force opened" )。
db2 = AppDatabase.buildDatabaseInstance(this,db2name,true)。
Log.d(AppDatabase.TAG,"File exists for " db1Name " " AppDatabase.doesDatabaseExist(this,db1Name))。
Log.d(AppDatabase.TAG,"File exists for " db2name " " AppDatabase.doesDatabaseExist(this,db2name))。
dao1 = db1.NoteDao();
dao2 = db2.NoteDao();
Log.d(AppDatabase.TAG,"Dao retrieved for " db1Name " accessing db via Dao" )。
dao1.getAll(); /* will open DB */.
Log.d(AppDatabase.TAG,"Dao retrieved for " db2name " accessing via Dao")。)
dao2.getAll(); /* would open DB BUT DB already opened */.
Log.d(AppDatabase.TAG,"File exists for " db1Name " " AppDatabase.doesDatabaseExist(this,db1Name))。
Log.d(AppDatabase.TAG,"File exists for " db2name " " AppDatabase.doesDatabaseExist(this, db2name))。
}
當第一次運行時,日志包括:-
2021-09-21 10:47: 54. 405 D/OPENINFO。檔案存在 for example1 false。
2021-09-21 10:47:54.405 D/OPENINFO: 檔案存在 for example2 false
2021-09-21 10:47:54.406 D/OPENINFO: 獲取實體 for example1 未強制打開
2021-09-21 10:47:54.415 D/OPENINFO: 獲取實體 for example2 force opened
2021-09-21 10:47:54.443 D/OPENINFO: OnCreate回呼被呼叫 for example2
2021-09-21 10:47:54。 450 D/OPENINFO: onOpen回呼被呼叫 for example2
2021-09-21 10:47:54.450 D/OPENINFO: 檔案存在 for example1 false
2021-09-21 10:47:54.450 D/OPENINFO: 檔案存在 for example2 true
2021-09-21 10:47:54.454 D/OPENINFO: Dao檢索到for example1通過Dao訪問db的資訊。
2021-09-21 10:47:54.478 D/OPENINFO: OnCreate回呼被呼叫 for example1
2021-09-21 10:47:54。 483 D/OPENINFO: onOpen回呼被呼叫 for example1
2021-09-21 10:47:54.487 D/OPENINFO: Dao檢索到for example2通過Dao訪問。
2021-09-21 10:47:54.490 D/OPENINFO: 檔案存在 for example1 true
2021-09-21 10:47:54.490 D/OPENINFO: 檔案存在 for example2 true
可以看出,example2的檔案(強制打開)在檢索實體后存在,而example1在試圖通過getAll()檢索資料前并不存在。
回呼的輸出確認相同。
從DeviceExplorer的角度來看,如果代碼只是(僅第一次運行):-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(s savedInstanceState)。
setContentView(R.layout.activity_main)。
/* 第一次運行,那么在這個階段兩個檔案都不應該存在,隨后的運行它們會存在 */
Log.d(AppDatabase.TAG, "File exists for " db1Name " " AppDatabase.doesDatabaseExist(this, db1Name))。
Log.d(AppDatabase.TAG, "File exists for " db2name " " AppDatabase.doesDatabaseExist(this, db2name))。
Log.d(AppDatabase.TAG, "Getting instance for " db1Name " not force opened")。
db1 = AppDatabase.buildDatabaseInstance(this, db1Name, false); /* not force open */
Log.d(AppDatabase.TAG, "Getting instance for " db2name " force opened" )。
db2 = AppDatabase.buildDatabaseInstance(this, db2name, true)。
Log.d(AppDatabase.TAG, "File exists for " db1Name " " AppDatabase.doesDatabaseExist(this, db1Name))。
Log.d(AppDatabase.TAG, "File exists for " db2name " " AppDatabase.doesDatabaseExist(this, db2name))。
}
然后設備資源管理器顯示:-
也就是說,example2已經被創建,但example1沒有被創建
而如果運行活動的全部代碼(僅第一次運行),則:-uj5u.com熱心網友回復:
我認為你缺少對資料庫的注釋。 添加這一行,就像下面這樣:
@Database(entities = Note.class,version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase appsDatabase。
public static synchronized AppDatabase getAppsDatabase(context context){
if (appsDatabase == null){
appsDatabase = Room.databaseBuilder(context,
AppDatabase.class,
"notes_db").build()。
}
return appsDatabase。
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/321072.html
標籤:


