[英]How do I delay Android Room loading until after activity and prompts complete?
問題:我收到null
數據庫名稱錯誤。 我的MainActiity.class
中的 Android Room 數據庫調用繼續執行,盡管提示讓用戶選擇數據庫名稱。
我正在嘗試做的事情:我仍在學習Android,但我正在嘗試在一個單獨的應用程序中工作,使用主Room
數據庫來管理應用程序使用的多個Room
數據庫的使用(這是一個沙盒類型的應用程序來玩這個想法)。 這個數據庫管理功能運行良好,但事情是硬編碼的。 因此,我正處於希望用戶能夠通過使用sharedPreferences
和自定義alert
提示的步驟中,可以選擇在安裝第一個房間數據庫名稱時創建並在其后添加其他名稱。 稍后添加它們的選項不是問題,因為將加載某些內容。 但是,在初始應用程序啟動時,我希望用戶可以選擇創建和命名第一個數據庫,而不是創建默認數據庫——這並不是什么大不了的事,但為什么用戶有一個潛在的默認數據庫從不使用。 我什至可以開發一種重命名方法,我會這樣做,但允許用戶這樣做似乎是有意義的。
我嘗試過的:我嘗試創建一些方法來封裝並從提示中分離出數據庫調用,但代碼仍然會傳遞到數據庫代碼。 我對延遲Room
進行了一些搜索,但找不到任何特定的內容。 我對他人的智慧持開放態度。
再次編碼,這只是一項活動,因為我正在玩這個想法......並同時學習。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "DB_INFO";
SharedPreferences sharedPreferences;
SharedPreferences.Editor settings;
String databaseName;
String prevDB;
Button button;
MasterDatabase masterDB;
List<MasterDatabaseList> mdbList;
ArrayList<BaseDatabase> bdbList = new ArrayList<>();
// Current Database
int currentBaseDBIndex = -1;
BaseDatabase currentDB = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
sharedPreferences = getSharedPreferences("AppSettings", MODE_PRIVATE);
settings = sharedPreferences.edit();
setupOnClickActions();
startChecks();
Toast.makeText(this, "database: " + databaseName + "\r\n" + "prevDB: " + prevDB, Toast.LENGTH_LONG).show();
}
private void startChecks(){
if(isFirstTime()) {
databaseName = PopupDialog.AlertInputBox(this, "Enter Research Project Name",
"Without spaces or special characters, enter a name for your research project.");
settings.putString("database", databaseName);
settings.commit();
settings.apply();
startDBs();
}else{
databaseName = PopupDialog.AlertInputBox(this, "Enter Research Project Name",
"Without spaces or special characters, enter a new or existing name for your research project.");
settings.putString("prevDB", sharedPreferences.getString("database", ""));
settings.putString("database", databaseName);
settings.commit();
settings.apply();
prevDB = sharedPreferences.getString("prevDB", "");
startDBs();
}
}
private void startDBs(){
masterDB = MasterDatabase.getInstance(this);
mdbList = masterDB.getMasterDao().getAllDatabases();
// Add a DB if none exists
if(mdbList.size()<1){
addBaseDB("sample.db");
}
setCurrentIndexDBandDao(databaseName); /* Add some data to db1 IF it exists (it should) --------------------- */
if (currentBaseDBIndex > -1 && currentDB.getBaseDao().count() < 1) {
currentDB.getBaseDao().insert(new BaseTable("Added " + databaseName + " ... etc."));
}
/* Extract and Log Data for ALL the BaseDatabase databases i.e. db1 and db2 */
for(MasterDatabaseList masterdb: masterDB.getMasterDao().getAllDatabases()) {
Log.d(TAG,"Database is " + masterdb.getDatabaseName());
setCurrentIndexDBandDao(masterdb.getDatabaseName());
if (currentBaseDBIndex > -1) {
for(BaseTable bt: currentDB.getBaseDao().getAllBaseTables()) {
Log.d(TAG,"Extracted Base Table row where MyData is" + bt.getMydata());
}
}
}
}
// METHODS =========================================================================================================
// Attempt to clear and reset SharedPreferences to a user first execution
private void setupOnClickActions(){
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
settings.putBoolean("firstTime", false);
settings.clear();
settings.commit();
settings.apply();
}
});
}
/* Add a new Database
Note that it assumes that it will now be the current
so the current values are set */
private void addBaseDB(String baseDBName) {
masterDB.getMasterDao().insert(new MasterDatabaseList(baseDBName));
}
/* Build/ReBuild the 3 Lists according to the master database*/
private void buildBaseLists() {
bdbList.clear();
mdbList = masterDB.getMasterDao().getAllDatabases();
// Loop through the databases defined in the master database adding the database and dao to the respective lists
for (MasterDatabaseList masterDB: masterDB.getMasterDao().getAllDatabases()) {
BaseDatabase baseDB = BaseDatabase.getInstance(this, masterDB.getDatabaseName());
bdbList.add(baseDB);
}
}
/* Set the currentDB according to the database name*/
private void setCurrentIndexDBandDao(String baseDBName) {
currentBaseDBIndex = getListIndexByBaseDBName(baseDBName);
if(currentBaseDBIndex == -1) {
addBaseDB(baseDBName);
buildBaseLists();
currentBaseDBIndex = getListIndexByBaseDBName(baseDBName);
}
if (currentBaseDBIndex > -1) {
buildBaseLists();
}
currentDB = bdbList.get(currentBaseDBIndex);
}
/* Get the index according to the database name passed*/
private int getListIndexByBaseDBName(String baseDBName) {
if(mdbList==null)
mdbList = masterDB.getMasterDao().getAllDatabases();
int rv = -1; // default to not found
for(int i=0; i < mdbList.size();i++) {
if (mdbList.get(i).getDatabaseName().equals(baseDBName)) {
rv = i;
break;
}
}
return rv;
}
/* Output all rows from the BaseTable for data extracted by the BaseDaos getAllBaseTables */
private void logBaseData(List<BaseTable> baseTableList) {
Log.d(TAG,"Current Database Index is " + currentBaseDBIndex + " DB name is " + mdbList.get(currentBaseDBIndex).getDatabaseName());
for(BaseTable bt: baseTableList) {
Log.d(TAG,"\tMyData value is " + bt.getMydata());
}
}
private boolean isFirstTime(){
if (sharedPreferences.getBoolean("firstTime", true)) {
settings.putBoolean("firstTime", false);
settings.commit();
settings.apply();
return true;
} else {
return false;
}
}
}
這是一個包含 2 個活動的示例。 第一個MainActivity
所以首先 MasterDatabaseList class (實體): -
@Entity(tableName = MasterDatabaseList.TABLE_NAME,
indices = { @Index(value = MasterDatabaseList.COL_DATABASE_NAME, unique = true)
}
)
class MasterDatabaseList {
public static final String TABLE_NAME = "masterdatabaselist";
public static final String COl_ID = "id";
public static final String COL_DATABASE_NAME = "databasename";
public static final String[] ALL_COLUMNS = new String[]{
COl_ID, COL_DATABASE_NAME
};
@PrimaryKey
@ColumnInfo(name = COl_ID)
Long id;
@ColumnInfo(name = COL_DATABASE_NAME)
String databaseName;
public MasterDatabaseList() {}
@Ignore
public MasterDatabaseList(String databaseName) {
this.databaseName = databaseName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDatabaseName() {
return databaseName;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
}
主數據庫道
@Dao
abstract class MasterDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(MasterDatabaseList masterDatabaseList);
@Query("SELECT * FROM masterdatabaselist")
abstract List<MasterDatabaseList> getAllDatabases();
Cursor getAllDatabasesAsCursor() {
MatrixCursor matrixCursor = new MatrixCursor(
new String[]{
BaseColumns._ID, /* Cursor Adapter must use _id column for id) */
MasterDatabaseList.COL_DATABASE_NAME
},
0
);
for(MasterDatabaseList m: getAllDatabases()) {
matrixCursor.addRow(new Object[]{m.id,m.databaseName});
}
return matrixCursor;
}
}
請注意將可用數據庫列表獲取為 Cursor 的新方法(對於 ListView)
主數據庫
@Database(entities = {MasterDatabaseList.class}, version = 1) 抽象 class MasterDatabase 擴展 RoomDatabase { abstract MasterDao getMasterDao();
static volatile MasterDatabase instance = null; public static MasterDatabase getInstance(Context context) { if (instance == null) { instance = Room.databaseBuilder(context,MasterDatabase.class,"master.db").allowMainThreadQueries().build(); } return instance; }
}
第二個活動UseSelectedDatabase
public class UseSelectedDatabase extends AppCompatActivity {
public static final String INTENT_EXTRA_DATABASEID = "database_id";
public static final String INTENT_EXTRA_DATABASENAME = "database_name";
long mDatabaseId;
String mDatabaseName;
TextView mDatabaseBeingUsed;
Button mDoneButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_use_selected_database);
mDatabaseBeingUsed = this.findViewById(R.id.database_name);
mDoneButton = this.findViewById(R.id.done);
mDatabaseId = this.getIntent().getLongExtra(INTENT_EXTRA_DATABASEID,-1);
mDatabaseName = this.getIntent().getStringExtra(INTENT_EXTRA_DATABASENAME);
mDatabaseBeingUsed.setText(mDatabaseName);
setDoneButton();
/*
can now get an instance of the database
*/
}
private void setDoneButton() {
mDoneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
}
第二個活動布局activity_use_selected_database.xml :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UseSelectedDatabase">
<TextView
android:id="@+id/database_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Database Set?"
>
</TextView>
<Button
android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DONE">
</Button>
</LinearLayout>
初始活動MainActivity :-
public class MainActivity extends AppCompatActivity {
MasterDatabase mMasterDB;
MasterDao mMasterDBDao;
EditText mDBToAdd;
Button mAddDB,mUseSelectedDatabase;
ListView mDatabaseList;
SimpleCursorAdapter mSCA;
Cursor mCsr;
long mSelectedDatabaseId = 0;
String mSelectedDatabaseName = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBToAdd = this.findViewById(R.id.database_name);
mAddDB = this.findViewById(R.id.addDatabase);
mUseSelectedDatabase = this.findViewById(R.id.useSelectedDatabase);
mDatabaseList = this.findViewById(R.id.database_list);
mMasterDB = MasterDatabase.getInstance(this);
mMasterDBDao = mMasterDB.getMasterDao();
setUpAddDBButton();
setUpUseSelectedDatabaseButton();
setOrRefreshDatabaseList();
}
private void setUpAddDBButton() {
mAddDB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mDBToAdd.getText().toString().length() > 0) {
if (mMasterDBDao.insert(new MasterDatabaseList(mDBToAdd.getText().toString())) > 0) {
mDBToAdd.setText("");
setOrRefreshDatabaseList();
}
}
}
});
}
private void setUpUseSelectedDatabaseButton() {
mUseSelectedDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mSelectedDatabaseId > 0) {
Intent intent = new Intent(view.getContext(),UseSelectedDatabase.class);
intent.putExtra(UseSelectedDatabase.INTENT_EXTRA_DATABASEID, mSelectedDatabaseId);
intent.putExtra(UseSelectedDatabase.INTENT_EXTRA_DATABASENAME,mSelectedDatabaseName);
startActivity(intent);
}
}
});
}
private void setOrRefreshDatabaseList() {
mCsr = mMasterDBDao.getAllDatabasesAsCursor();
if (mSCA == null) {
mSCA = new SimpleCursorAdapter(
this.getApplicationContext(),
android.R.layout.simple_list_item_1,
mCsr,
new String[]{MasterDatabaseList.COL_DATABASE_NAME},
new int[]{android.R.id.text1},
0
);
mDatabaseList.setAdapter(mSCA);
mDatabaseList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
/* Handle Clicking on an Item (i.e. prepare UseSelected Button) */
@SuppressLint("Range")
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
mSelectedDatabaseId = l;
if (l > 0) {
mSelectedDatabaseName = mCsr.getString(mCsr.getColumnIndex(MasterDatabaseList.COL_DATABASE_NAME));
mUseSelectedDatabase.setText(mSelectedDatabaseName);
mUseSelectedDatabase.setClickable(true);
} else {
mUseSelectedDatabase.setText("NO DATEBASE SELECTED");
mUseSelectedDatabase.setClickable(false);
}
}
});
} else {
mSCA.swapCursor(mCsr);
}
}
@Override
protected void onResume() {
super.onResume();
setOrRefreshDatabaseList();
}
@Override
protected void onDestroy() {
super.onDestroy();
mCsr.close();
}
}
初始Activity的布局activity_main.xml :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<EditText
android:id="@+id/database_name"
android:layout_width="500dp"
android:layout_height="wrap_content"
android:text="">
</EditText>
<Button
android:id="@+id/addDatabase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Database"
>
</Button>
<ListView
android:id="@+id/database_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
<Button
android:id="@+id/useSelectedDatabase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NO SELECTED DATABASE"
android:clickable="false"
>
</Button>
</LinearLayout>
演示
首次運行 MainActivity 時顯示:-
即沒有可用的數據庫(單擊按鈕什么都不做)。
數據庫 Test001 進入編輯文本,然后單擊添加數據庫:-
點擊Test001:-
將數據庫 Test002 輸入到編輯文本中(添加后清除)並單擊添加數據庫:-
單擊 Test002,按鈕變為 Test002 並單擊按鈕,開始第二個活動:-
單擊 DONE 按鈕返回到第一個活動。 仍然沒有打開/訪問數據庫,但其他代碼(Base???? clases 等)可能是(可能在 UseSelectedDatabase 活動中)。
額外作為 BaseTable 的概念證明??? 添加了上一個問題中的類,以及一些新用戶??? BaseDatabase的類是:-
@Database(
entities = {BaseTable.class,User.class},
version = 1
)
abstract class BaseDatabase extends RoomDatabase {
abstract BaseDao getBaseDao();
abstract UserDao getUserDao();
public static BaseDatabase getInstance(Context context, String databaseName) {
BaseDatabase db = Room.databaseBuilder(context, BaseDatabase.class, databaseName)
.allowMainThreadQueries()
.build();
db.getOpenHelper().getWritableDatabase();
return db;
}
}
將以下內容添加到UseSelectedDatabase活動中:-
....
/*
can now get an instance of the database
*/
db = BaseDatabase.getInstance(this,mDatabaseName);
baseDao = db.getBaseDao();
userDao = db.getUserDao();
baseDao.insert(new BaseTable("X"));
userDao.insert(new User("Snowman","Fred","Wlibur","Bloggs","password",0));
List<BaseTable> baseTableList = baseDao.getAllBaseTables();
List<User> userList = userDao.getAllUsers();
重新啟動應用程序選擇 Test001,然后選擇 Test002 導致數據庫顯示為:-
即Test001,盡管它已關閉,但顯然已像Test002 一樣創建。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.