簡體   English   中英

如何將 Android 房間加載延遲到活動和提示完成之后?

[英]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

  • 顯示可用數據庫的列表(一開始沒有)
    • 單擊數據庫允許選擇它(它不被訪問或創建(如果是新的))
  • 允許通過在 EditText 中輸入數據庫的名稱來將數據庫添加到可用的數據庫中(它不是創建或訪問的)。
  • 允許將第二個活動傳遞給活動可以打開數據庫的數據庫名稱(如果它不存在則創建它)。
    • 請注意,未訪問數據庫。

所以首先 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();
            }
        });
    }
}
  • 這不會訪問數據庫,而只是接收主數據庫中的數據庫名稱和 ID。 ie 只是表明您可以傳遞訪問數據庫所需的所有信息。

第二個活動布局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 數據庫。 然而,MasterDatabase 已經創建並添加了 Test001 行(即,如果數據庫不存在,有時可以打開和創建數據庫):-

在此處輸入圖像描述

點擊Test001:-

在此處輸入圖像描述

  • Use Selected 按鈕已更改為 Test001(可能應該是 Use 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM