Android開發筆記(一百七十八)更安全的資料倉儲DataStore

2021-12-31 11:00:02

雖然SharedPreferences用起來比較方便,但是在一些特殊場景會產生問題。比如共用引數儲存的資料較多時,初始化共用引數會把整個檔案載入進記憶體,載入耗時可能導致主執行緒堵塞。又如呼叫apply方法儲存資料時,頻繁apply容易導致執行緒等待超時。為此Android官方推出了資料倉儲DataStore,並將其作為Jetpack庫的基礎元件。DataStore提供了兩種實現方式,分別是Preferences DataStore 和Proto DataStore,前者採用鍵值對儲存資料,後者採用自定義型別儲存資料,其中Preferences DataStore可以直接替代SharedPreferences。
由於DataStore並未整合到SDK中,而是作為第三方框架提供,因此首先要修改模組的build.gradle檔案,往dependencies節點新增下面兩行設定,表示匯入指定版本的DataStore庫:

implementation "androidx.datastore:datastore-preferences:1.0.0"
implementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0"

資料倉儲的用法類似於共用引數,首先要指定倉庫名稱,並建立倉庫範例,範例程式碼如下:

private RxDataStore<Preferences> mDataStore; // 宣告一個資料倉儲範例

private DatastoreUtil(Context context) {
    mDataStore = new RxPreferenceDataStoreBuilder(context.getApplicationContext(), "datastore").build();
}

// 獲取資料倉儲工具的範例
public static DatastoreUtil getInstance(Context context) {
    if (instance == null) {
        instance = new DatastoreUtil(context);
    }
    return instance;
}

其次從倉庫範例中獲取指定鍵名的資料,下面的程式碼模板演示瞭如何從資料倉儲中讀取字串值:

// 獲取指定名稱的字串值
public String getStringValue(String key) {
    Preferences.Key<String> keyId = PreferencesKeys.stringKey(key);
    Flowable<String> flow = mDataStore.data().map(prefs -> prefs.get(keyId));
    try {
        return flow.blockingFirst();
    } catch (Exception e) {
        return "";
    }
}

往倉庫範例寫入指定鍵值的話,下面的程式碼模板演示瞭如何將字串值寫入資料倉儲:

// 設定指定名稱的字串值
public void setStringValue(String key, String value) {
    Preferences.Key<String> keyId = PreferencesKeys.stringKey(key);
    Single<Preferences> result = mDataStore.updateDataAsync(prefs -> {
        MutablePreferences mutablePrefs = prefs.toMutablePreferences();
        mutablePrefs.set(keyId, value);
        return Single.just(mutablePrefs);
    });
}

前面把資料倉儲的初始化以及讀寫操作封裝在DatastoreUtil中,接下來通過該工具類即可方便地存取資料倉儲了。往資料倉儲儲存資料的程式碼範例如下:

// 從資料倉儲中讀取資訊
private void readDatastore() {
    DatastoreUtil datastore = DatastoreUtil.getInstance(this); // 獲取資料倉儲工具的範例
    String desc = "資料倉儲中儲存的資訊如下:";
    desc = String.format("%s\n %s為%s", desc, "姓名",
            datastore.getStringValue("name"));
    desc = String.format("%s\n %s為%d", desc, "年齡",
            datastore.getIntValue("age"));
    desc = String.format("%s\n %s為%d", desc, "身高",
            datastore.getIntValue("height"));
    desc = String.format("%s\n %s為%.2f", desc, "體重",
            datastore.getDoubleValue("weight"));
    desc = String.format("%s\n %s為%b", desc, "婚否",
            datastore.getBooleanValue("married"));
    desc = String.format("%s\n %s為%s", desc, "更新時間",
            datastore.getStringValue("update_time"));
    tv_data.setText(desc);
}

從資料倉儲獲取資料的程式碼範例如下:

DatastoreUtil datastore = DatastoreUtil.getInstance(this); // 獲取資料倉儲工具的範例
datastore.setStringValue("name", name); // 新增一個名叫name的字串
datastore.setIntValue("age", Integer.parseInt(age)); // 新增一個名叫age的整數
datastore.setIntValue("height", Integer.parseInt(height)); // 新增一個名叫height的整數
datastore.setDoubleValue("weight", Double.parseDouble(weight)); // 新增一個名叫weight的雙精度數
datastore.setBooleanValue("married", isMarried); // 新增一個名叫married的布林值
datastore.setStringValue("update_time", DateUtil.getNowDateTime("yyyy-MM-dd HH:mm:ss"));

執行測試App,先開啟記錄儲存頁面,填寫資料後點選儲存按鈕,此時儲存介面如下圖所示。


然後開啟記錄獲取介面,看到記錄獲取結果如下圖所示,說明成功實現了資料倉儲的讀寫功能。

 

 


點此檢視Android開發筆記的完整目錄