Android技術中哪一種存儲技術最容易理解和使用,沒錯,就是標題上所說的SharedPreferences
, 實際上,SharedPreferences
處理的就是一個個key-value對。
一. 使用SharedPreferences存儲數據
使用 SharedPreferences 保存key-value對的步驟一般是這樣:
- 使用Activity類的getSharedPreferences方法獲取到 SharedPreferences 對象,指定文件名和訪問權限
- 獲得SharedPreferences.Editor對象,并使用該對象的 putXxx方法保存key-value對。
- 通過SharedPreferences.Editor的commit方法保存(提交)key-value對。
實例:
程序退出,再次啟動時,顯示出上次在EditText控件中填寫的內容。
在Activity生命周期的回調方法onStop中保存數據:
@Override
protected void onStop() {
//獲取一個文件名為test、權限為private的xml文件的SharedPreferences對象
SharedPreferences sharedPreferences = getSharedPreferences("test", MODE_PRIVATE);
//得到SharedPreferences.Editor對象,并保存數據到該對象中
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("name", et_name.getText().toString().trim());
//保存key-value對到文件中
editor.commit();
super.onStop();
}
當然 SharedPreferences 提供可以直接保存的數據格式不僅只有String,還有 int、boolean、float、long以及Set<String>。
在onCreate方法中獲取數據,回顯
et_name = (EditText) findViewById(R.id.et_name);
SharedPreferences sharedPreferences = this.getSharedPreferences("test", MODE_PRIVATE);
et_name.setText(sharedPreferences.getString("name",""));
二. 數據的存儲位置和格式
實際上,SharedPreferences 將數據文件寫在了手機內存私有的目錄中該app的文件夾下。
可以通過DDMS的【File Explorer】找到data\data\程序包名\shared_prefs目錄(如果使用真機測試,必須保存已root,否則因為權限問題無法進入data目錄),發現test.xml
文件。導出文件并查看:
<!-- test.xml -->
<?xml version='1.0' encoding='utf-8' standalone='yes'>
<map>
<string name="name">小明</string>
</map>
三. 存取復雜類型的數據
如果要用 SharedPreferences 存取復雜的數據類型(類,圖像等),就需要對這些數據進行編碼。通常會將復雜類型的數據轉換成Base64編碼,然后將轉換后的數據以字符串的形式保存在XML文件中。
實例:
使用 SharedPreferences 保存Product
類的一個對象和一張圖片。
界面如下:
提供了兩Button,用來保存和獲取使用 SharedPreferences 保存的Product對象和圖片。
保存按鈕的點擊事件:
bt_prod_save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
//保存對象
Product product = new Product();
product.setId(et_prod_id.getText().toString().trim());
product.setName(et_prod_name.getText().toString().trim());
SharedPreferences sharedPreferences = getSharedPreferences("base64", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(product);
String base64Product = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
editor.putString("product", base64Product);
//保存圖片
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
((BitmapDrawable) getResources().getDrawable(R.drawable.lanbojini)).getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, baos2);
String imageBase64 = Base64.encodeToString(baos2.toByteArray(), Base64.DEFAULT);
editor.putString("productImg", imageBase64);
editor.commit();
baos.close();
oos.close();
Toast.makeText(MainActivity.this, "保存成功!??!", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "保存出錯了?。。? + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
回顯按鈕的點擊事件:
bt_prod_show.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
//獲取對象
et_prod_id = (EditText) findViewById(R.id.et_prod_id);
et_prod_name = (EditText) findViewById(R.id.et_prod_name);
SharedPreferences sharedPreferences = getSharedPreferences("base64", MODE_PRIVATE);
String productString = sharedPreferences.getString("product", "");
byte[] base64Product = Base64.decode(productString, Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(base64Product);
ObjectInputStream ois = new ObjectInputStream(bais);
Product product = (Product) ois.readObject();
et_prod_id.setText(product.getId());
et_prod_name.setText(product.getName());
//獲取圖片
iv_prod_img = (ImageView) findViewById(R.id.iv_prod_img);
byte[] imagByte = Base64.decode(sharedPreferences.getString("productImg",""), Base64.DEFAULT);
ByteArrayInputStream bais2 = new ByteArrayInputStream(imagByte);
iv_prod_img.setImageDrawable(Drawable.createFromStream(bais2, "imagByte"));
} catch (Exception e) {
e.printStackTrace();
}
}
});
原理:使用Base64
把Product對象和圖片進行編碼成字符串后,然后通過 SharedPreferences 把轉換后的字符串保存到xml文件中,在需要使用該對象或者圖片時,通過Base64
把從 SharedPreferences 獲取的字符串解碼成對象或者圖片再使用。
查看base64.xml
文件,會看到如下內容:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="productImg">/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABALDA4MChAOoOjM9PDkz......
</string>
<string name="product">rO0ABXNyACNjbHViLmxldGdldC50ZXN0c2hhGJqb......
</string>
</map>
注意:
雖然可以采用編碼的方式通過 SharedPreferences 保存任何類型的數據,但不建議使用 SharedPreferences 保存尺寸很大的數據。如果要存取更多的數據,一般使用文件存儲、SQLite數據庫等技術。
四. 設置數據文件的訪問權限
大家都知道,Android系統本質上是Linux,那么Android文件權限也和Linux一致。
Linux文件屬性分為4段,
第一段:
[d]:表示目錄
[-]:表示文件
[l]:表示鏈接文件
[b]:表示可供存儲的接口設備文件
[c]:表示串口設備文件,例如鍵盤、鼠標
第二段:
[r]:表示可讀
[w]:表示可寫
[x]:表示可執行
如果不具備某個屬性,該項將以[-]代替,例如rw-、--x等
第三段和第四段和第二段相同,區別在于,第二段表示文件所有者擁有的權限,第三段表示文件所有者所在的用戶組中其他用戶的權限,第四段表示其他用戶的權限。
例如:-rw-rw-rw,表示這是一個文件,并且該用戶和該組內其他用戶和其他用戶的權限都為可讀和可寫不可執行。
我們在獲取 SharedPreferences 對象時,使用的是下面這行代碼:
SharedPreferences sharedPreferences = this.getSharedPreferences("test", MODE_PRIVATE);
其中getSharedPreferences
方法第二個參數就是對文件權限的描述。
這個參數有四個可選值:
Activity.MODE_PRIVATE:表示該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容
Activity.MODE_APPEND:也是私有數據,新寫入的內容會追加到原文件中
Activity.MODE_WORLD_READABLE:表示當前文件可以被其他應用讀取
Activity.MODE_WORLD_WRITEABLE:表示當前文件可以被其他應用寫入
END