Android本地數據存儲方案(一)

Android系列的博客主要是記錄和總結自己在平時學習之中遇到的問題,方便日后用到時查看,同時也希望對讀者有所幫助。不足之處,歡迎指正~


在說到Android數據存儲之前,先提一下數據持久化,所謂數據持久化就是將內存中的瞬時數據保存下來,在應用開發中是很重要的部分。舉個栗子,我們打開一個應用之后輸入了用戶名和密碼,之后回到了桌面,再回到應用時,我們希望之前輸入的內容還在,這個要怎么實現呢?可以在回到桌面時將數據保存,返回視圖時再填入數據。

其實不止是這些瞬時數據的保存,包括一些和應用相關的數據也是需要保存的,比如用戶第一次登陸之后,之后再進入應用不必再次登陸,那么用戶的信息就需要保存下來。下面進入正題。

注意:數據持久化應該結合Activity的生命周期使用。

Android本地數據存儲有以下幾種方式:

  1. SharedPreferences:用戶偏好設置
  2. 內部存儲,數據存儲到手機內置存儲器
  3. 外部存儲,外部SD卡中存儲數據
  4. SqlLite本地數據庫存儲
  5. ContentProvider

其中內部存儲和外部存儲都屬于文件存儲,這次主要是介紹SharedPreferences和內部存儲。

1. SharedPreferences:用戶偏好設置

SharedPreferences使用鍵值對來存儲數據,默認以xml文件形式進行存儲,對應的文件保存到手機內存的data/<application package>/xxx(保存數據時建立的文件)目錄下面,提供和putString(),putInt(),putBoolean()等方法存儲不同類型的數據,使用時很方便。

因為SharedPreferences存儲時的數據格式和數據類型限制,它只適用于存儲一些簡單用戶設置,例如用戶設置的夜間模式,音量,或者登錄信息等。

如何獲取SharedPreferences

Android提供了3中方法獲取SharedPreferences對象。

1) Context 類中的 getSharedPreferences()方法

參數:getSharedPreferences()需要如下兩個參數
String類型:指定文件名(不需要帶文件后綴)
int類型:指定文件的操作模式,常用的是MODE_PRIVATE (該文件只允許本應用程序進行讀寫),MODE_APPEND(對文件進行寫入操作時,是在文件尾追加內容),MODE_MULTI_PROCESS (用于會有多個進程中對同一個 SharedPreferences 文件進行讀寫的情況)。

2) Activity 類中的 getPreferences()方法

參數:只接收一個操作模式參數。
這個方法時會自動將當前活動的類名作為 SharedPreferences 的文件名。

3) PreferenceManager 類中的 getDefaultSharedPreferences()方法

這是一個靜態方法,它接收一個 Context 參數,并自動使用當前應用程序的包名作為前綴來命名 SharedPreferences 文件

以下是代碼案例(以保存登錄信息為例):
獲取SharedPreferences對象

preferences = getSharedPreferences("login",MODE_PRIVATE);

存儲用戶登錄的信息

//獲取editor對象
    SharedPreferences.Editor editor = preferences.edit();
   //存儲數據時選用對應類型的方法
    editor.putString("userId",user.getUserId());
    editor.putString("username",user.getUserName());
    editor.putString("password",user.getPassword());
    editor.putString("role",user.getUserRole());
    //提交保存數據
    editor.commit();

取出數據
取出數據之前要先獲得SharedPreferences對象。

//取出數據,第一個參數是存取的鍵,第二個參數-->如果該key不存在,返回默認值,這里返回的默認值是""
    String userId = preferences.getString("username","");
    String password = preferences.getString("password","");
    String role = preferences.getString("role","");

2. 文件存儲

文件存儲的形式不對文件進行任何格式化處理,存入是什么樣,取出來也是什么樣,我們可以用它存儲一些簡單類型的數據或二進制數據,也可以自己定義存儲規范,用來存儲復雜的文本數據。其實我們可以直接存儲json格式的數據在文件中,借助Gson類進行對象和json格式之間的轉換,使用很方便。上次我就在應用中用文件緩存了數據,比起SQLLite,有時文件存儲要方便一些,因為它不用進行創建數據庫,建表等操作。

內部存儲:Context提供了很方便的打開文件的方法。可以使用Context類提供的openFileOutput (),和openFileInput ()進行文件寫入和讀取,進行緩存的設置和讀取,需要注意的是,這里傳入的文件名是帶有文件后綴的。
注意:在讀寫是文件時可以加入讀寫緩沖,加快讀寫效率。

以下是文件存儲的內部存儲的例子(以存儲字符串為例):
為了以后使用方便,可以先定義一個文件緩存的工具類。

public class FileCacheUtil {
    //定義緩存文件的名字,方便外部調用
    public static final String docCache = "docs_cache.txt";//緩存文件
    //緩存超時時間
    public static final int CACHE_SHORT_TIMEOUT=1000 * 60 * 5; // 5 分鐘

    /**設置緩存
    content是要存儲的內容,可以是任意格式的,不一定是字符串。
    */
    public static void setCache(String content,Context context, String cacheFileName,int mode) {
        FileOutputStream fos = null;
        try {
            //打開文件輸出流,接收參數是文件名和模式
            fos = context.openFileOutput(cacheFileName,mode);
            fos.write(content.getBytes());
         } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //讀取緩存,返回字符串(JSON)
    public static String getCache(Context context, String cacheFileName) {
        FileInputStream fis = null;
        StringBuffer sBuf = new StringBuffer();
        try {
            fis = context.openFileInput(cacheFileName);
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = fis.read(buf)) != -1) {
                sBuf.append(new String(buf,0,len));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if(sBuf != null) {
             return sBuf.toString();
        }
        return null;
    }

    public static String getCachePath(Context context) {
        return context.getFilesDir().getAbsolutePath();
    }
}

使用
使用文件緩存工具類時,直接調用它對外提供的函數就可以,將需要數據以字符串形式存,我們可以自定義數據存儲格式,比如說以JSON串存儲。以上代碼中,緩存文件名寫到文件緩存的類中,使用的時候可以直接調用。

提示:可以在Activity的onResume()的方法中使用獲取緩存的操作(結合Activity來看),在onPause()是使用設置緩存的操作(暫停,跳轉到其他Activity時調用這個方法)。

在應用中我們可以根據是否有網絡或著緩存是否過期來判斷是否從文件中獲取緩存數據。以下是判斷緩存是否過期的方法。

//判斷緩存是否過期,比較文件最后修改時間
private boolean cacheIsOutDate(String cacheFileName) {    
    File file = new File(FileCacheUtil.getCachePath(mContext) + "/" 
                 + cacheFileName);    
    //獲取緩存文件最后修改的時間,判斷是是否從緩存讀取    
    long date = file.lastModified();    
    long time_out = (System.currentTimeMillis() - date);    
    if (time_out > FileCacheUtil.CACHE_SHORT_TIMEOUT) {           
        return true;    
    }       
    return false;//未過期
}

總結

最后總結一下Context中獲取內部存儲和外部存儲文件路徑的方法。這些目錄下的文件都會隨著應用的卸載而被刪除。
context.getFilesDir():獲取手機內置存儲器的/data/data/<application package>/files目錄,這個位置放存儲文件。
context.getCacheDir():獲取手機內置存儲器的/data/data/<application package>/cache目錄,這個目錄可以存放應用緩存文件。
context.getExternalFilesDir():獲取SDCard/Android/data/你的應用的包名/files/ 目錄,是外部存儲的目錄,當我們使用外部存儲時,應該先判斷外部存儲介質是否存在,同時還要在應用權限中加入對sd卡的讀寫操作。

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

推薦閱讀更多精彩內容

  • 任何一個應用程序,其實說白了就是在不停地和數據打交道,我們聊QQ、看新聞、刷微博,所關心的都是里面的數據,...
    AndYMJ閱讀 1,712評論 2 5
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,098評論 25 708
  • 最近在折騰完房子之后,開始考慮自己的職業發展,準備試試新機會,謀求一個突破。 然后就是一個又一個打擊,要么被待定,...
    bluescorpio閱讀 968評論 0 1
  • 你學習一般,考上了現在的這所學校,成績不算好,拿不到獎學金,上課不聽講,上自習不規律,考試靠突擊,同學幫一把的話也...
    胡星星閱讀 191評論 0 0
  • 清泉石上流,無聲石字留; 篆書鐫刻成,有緣石自秀; 山河孕千年,相會不舍丟; 勤放書案前,信心誠石修。 ...
    一真書苑閱讀 501評論 3 2