2016年1月29日 星期五

Android 的 SharedPreferences 學習筆記

Android 的 SharedPreferences 是一種提供 App 儲存少量資料的物件。要使用 SharedPreferences 需要 import android.content.SharedPreferences;

SharedPreferences 是用 Key, Value 的方式組成,就像我們在使用 NoSQL 一樣,key 就是鍵名,value 就是值,下面介紹增修刪讀一個 SharedPreferences 的方式 (其實就只是參考官方文件)。

建立 SharedPreferences 物件

在一個 APP 使用 SharedPreferences 儲存資料,首先要先建立起 SharedPreferences 的物件:

getSharedPreferences 變數名稱  = getSharedPreferences(String name, int MODE);

// Example 建立名為 pref 的 SharedPreferences 物件
SharedPreferences pref = getSharedPreferences("dialogAppFile", MODE_PRIVATE);

getSharedPreferences 有兩個參數,getSharedPreferences(String name, int MODE);

第一個參數  name 型別為 String,表示檔名,SharedPreferences 會去找符合檔名的 ShredPreferences,假如檔名不存在,那麼他會當你在使用 editor (SharedPreferences.edit()) 而且 commit (意思就是送出更新或是建立 key 值) 的時候建立。

因為 SharedPreferences 是 XML 檔的格式,所以只需要帶入檔名,副檔名就不需要了。

附帶一提,這裏的 Editor 是指 SharedPreferences 的 Editor 物件,要先拿到這個物件,才能寫入資料到 ShredPreferences,下面在 "寫入資料到SharedPreferences" 地方會再提到,只要先知道如果檔案不存在,它也會在操作 commit 時建立。

第二個參數雖然是 int 型別,但是值是預設的幾種常數在使用, 這裏的 MODE 指的是 operation mode,設定這個檔案的存取權限的意思,預設會是 MODE_PRIVATE (真正儲存的值是 0)。

幾種 MODE:
* MODE_PRIVATE: 只有自己這隻 APP(應用程式) 才能存取。
* MODE_WORLD_READABLE: 所有應用程式都可以讀取。(這個常數會在 API level 17 被棄用 This constant was deprecated in API level 17.)
* MODE_WORLD_WRITEABLE: 所有應用程式都可以寫入。(這個常數會在 API level 17 被棄用 This constant was deprecated in API level 17.)

所以,通常我建立的 key 值可能只跟我正在開發的 APP 有關,就可以使用 MODE_PRIVATE,也就是只有該應用程式才可以存取。


讀取/寫入資料到 SharedPreferences

假如你正在開發一支手機遊戲,你可以會希望記錄使用者目前玩到的關卡到  SharedPreferences 裡面,所以當 user 開啟 APP 時,我們會從 SharedPreferences 拿出他上一次的紀錄,當然當使用者玩到升級的時候,也就要更新 SharedPreferences 的關卡紀錄,所以,關卡紀錄就是一個 key,儲存的是當下的關卡等級。

由這段描述,先去思考怎麼拿 key 值出來。讀取資料比寫入, 移除還要容易一點,因為寫入移除資料還需要額外呼叫 Editor 物件,讀! ,只要有建立 SharedPreferences 物件,直接使用 getkey的資料型別(key值, 預設值) 就行!

假設我當初存在 SharedPreferences 的關卡等級型別是 String,key 是 gameLevel,那麼拿取 gameLevel 的方法會像:

SharedPreferences pref = getSharedPreferences("dialogAppFile", MODE_PRIVATE);
String gameLevel = pref.getString("gameLevel", "no value");

因為 gameLevel 的型別是 String,所以要用  getString(...),假如今天存的是 int,就會是 getInt(...),所以這邊的 get 有很多種 case,端看當初進去的型別是什麼。

ex: getBoolean, getFloat, getInt, getLong, getString....

第二個參數我帶入 no value,表示沒有取得到 gameLevel 這個 key 的值的話,預設回傳值就是 no value。


再來介紹寫入
寫入,寫入資料到 SharedPreferences 需要額外建立 Editor 物件:

Editor 變數名稱 = SharedPreferences 物件名稱 .edit();
SharedPreferences pref = getSharedPreferences("dialogAppFile", MODE_PRIVATE);
SharedPreferences.Editor editor =  pref.edit();

上面這一段,建立 Editor 物件並儲存在名為 editor 的變數。

用建立好的 editor,呼叫 putkey的資料型別(key值, 值),你可以一次 put 好幾組想要儲存的 key,但是 put 只是建立 key,並沒有真的儲存的動作,真正的儲存還要呼叫 commit()。

假如我要建立 username, nickname 的 key:
// put 只是寫入,並沒有真的儲存
editor.putString("username", "win wu");
editor.putString("nickname", "小win");
/*  要呼叫commit 才是真的儲存,在這邊 commit,會一次儲存前面的put  也就是 username, nickname 都會在 commit 的時候儲存  */
editor.commit();

然後要把 username 拿出來就用 getString(...):
String username = pref.getString("username", "no name");
// log 出 username 的值
Log.d("WINWU_APP_LOG", username);

假如,一直針對同一個 key 做 put,就會蓋掉舊的 (前提是記得 commit)。其實 put 也有更新的意思。


移除 Key 值
移除 key 一樣需要 Editor 物件來操作,你可以使用 remove("key值")。
editor
    .remove("username")
    .commit();
String username = pref.getString("username", "名字已不存在");
Log.d("WINWU_APP_LOG", username);


清除全部的資料
其實看到現在會發現,只要需要更動到 SharedPreferences 檔案的內容,都需要使用 Editor 物件,所以目前也只有讀取 key 值用不到 Editor。

清空 preferences 檔案裡面的 key,呼叫 clear() 然後再 commit() 就行。
editor
    .clear()
    .commit();


我的 SharedPreferences 存在哪裡?
利用程式操作 SharedPreferences 其實是有點空虛,但確實真的有這個檔案存在,格式為 XML,你可以開啟 Android Device Monitor,然後點選 File Explore,通常應用程式的資料會放在 data/data 資料夾底下,接著尋找應用程式的 applicationId 取名的資料夾。

[在 Android Studio 靠右邊的這一顆可以開啟 Android Device Monitor]

[找到 File Explore]

SharedPreferences 就放在應用程式的資料夾底下 shared_prefs/preFile.xml。

你沒有辦法直接夠過 device monitor 開啟這個檔案,但你可以把它匯出來看看,右上角找一下 icon,有個 pull a file from device。

這是 SharedPreferences  xml 的樣子,你會看到你儲存的 key 值:


End~

沒有留言:

張貼留言

若你看的文章,時間太久遠的問題就別問了,因為我應該也忘了... XD

Vue multiselect set autofocus and tinymce set autofocus

要在畫面一進來 focus multiselect 的方式: 參考: https://jsfiddle.net/shentao/mnphdt2g/ 主要就是在 multiselect 的 tag 加上 ref (例如: my_multiselect), 另外在 mounted...