Android中最簡單的數據存儲方式:SharedPreferences

Android技術中哪一種存儲技術最容易理解和使用,沒錯,就是標題上所說的SharedPreferences , 實際上,SharedPreferences 處理的就是一個個key-value對。

一. 使用SharedPreferences存儲數據

使用 SharedPreferences 保存key-value對的步驟一般是這樣:

  1. 使用Activity類的getSharedPreferences方法獲取到 SharedPreferences 對象,指定文件名和訪問權限
  2. 獲得SharedPreferences.Editor對象,并使用該對象的 putXxx方法保存key-value對。
  3. 通過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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,353評論 25 708
  • permissionn.允許;批準,正式認可,認可user permission 使用權限permission D...
    lengol閱讀 1,049評論 0 51
  • 面試題總結 通用 安卓學習途徑, 尋找資料學習的博客網站 AndroidStudio使用, 插件使用 安卓和蘋果的...
    JingBeibei閱讀 1,715評論 2 21
  • 文 | 私塾先生 現在流行一個概念,叫“共享經濟”。我私自揣測,主要是因為很多東西我們想使用,但是卻不想、或者不易...
    私塾先生lilz閱讀 287評論 0 2
  • 過年這些天,微信紅包都被玩壞了。所有的互聯網新聞、公眾賬號、各類大牛等等等,無一不在討論這個應節的產品。從互聯網愛...
    pb1022閱讀 2,008評論 7 4