Android数据存储与持久化
一、持久化技術簡介
瞬時數據是指那些存儲在內存當中,有可能會因為程序關閉或其他原因導致內存被回收而丟失的數據。這對于一些關鍵性的數據信息來說是絕對不能容忍的,誰都不希望自己剛發出去的一條微博,刷新一下就沒了吧。那么怎樣才能保證讓一些關鍵性的數據不會丟失呢?這就需要用到數據持久化技術了
數據持久化就是指將那些內存中的瞬時數據保存到存儲設備中,保證即使在手機或電腦關機的情況下,這些數據仍然不會丟失。保存在內存中的數據是處于瞬時狀態的,而保存在存儲設備中的數據是處于持久狀態的,持久化技術則是提供了一種機制可以讓數據在瞬時狀態和持久狀態之間進行轉換
持久化技術被廣泛應用于各種程序設計的領域當中,而本書中要探討的自然是Android中的數據持久化技術。Android 系統中主要提供了三種方式用于簡單地實現數據持久化功能,即文件存儲、SharedPreference 存儲以及數據庫存儲。當然,除了這三種方式之外,你還可以將數據保存在手機的SD 卡中,不過使用文件、SharedPreference 或數據庫來保存數據會相對更簡單一些,而且比起將數據保存在SD 卡中會更加的安全
以上引用自郭霖的《第一行代碼》
二、SharedPreferences
使用鍵值對的方式來存儲數據,SharedPreferences 文件都是存放在/data/data/<packagename>/shared_prefs/目錄下的
獲取SharedPreferences 對象的三種方法
1、Context 類中的getSharedPreferences()方法
2、Activity 類中的getPreferences()方法
3、PreferenceManager 類中的getDefaultSharedPreferences()方法
寫數據到SharedPreferences 中
為了把數據寫入SharedPreferences文件,需要通過執行edit()創建一個 SharedPreferences.Editor,然后通過Editor對象的putXxx()方法存入鍵值對數據,最后commit()方法提交數據
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit(); editor.putInt(getString(R.string.saved_high_score), newHighScore); editor.commit();從SharedPreferences 中讀取數據
public class Calc extends Activity {public static final String PREFS_NAME = "MyPrefsFile";@Overrideprotected void onCreate(Bundle state){super.onCreate(state);// Restore preferencesSharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);boolean silent = settings.getBoolean("silentMode", false);setSilent(silent);}@Overrideprotected void onStop(){super.onStop();// We need an Editor object to make preference changes// All objects are from android.context.ContextSharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);SharedPreferences.Editor editor = settings.edit();editor.putBoolean("silentMode", mSilentMode);// Commit the edits!editor.commit();} }三、手機內存
保存在手機內存的數據是應用私有的,別的應用沒有權限訪問,當用戶卸載應用的時候,數據也會隨之被刪除
通過Activity的openFileOutput()和 openFileInput()方法可以拿到輸出流和輸入流,然后通過流讀寫數據
1、創建并寫入文件到手機內存
String FILENAME = "hello_file"; String string = "hello world!";FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(string.getBytes()); fos.close();openFileOutput(),參數1:文件名,參數2:文件訪問模式,文件默認存儲到/data/data/<packagename>/files/ 目錄下的
| MODE_PRIVATE | 私有模式,默認的操作模式,表示當指定同樣文件名的時候,所寫入的內容將會覆蓋原文件中的內容 |
| MODE_WORLD_READABLE | 只讀模式,API 17后過時 |
| MODE_WORLD_WRITEABLE | 只寫模式,API 17后過時 |
| MODE_APPEND | 追加模式,如果該文件已存在就往文件里面追加內容,不存在就創建新文件 |
Android 7.0 之后,使用 FileProvider分享私有數據
2、從手機內存讀取文件
FileInputStream inputStream = null;try {inputStream = openFileInput(FILENAME);...} catch (Exception e) {e.printStackTrace();}finally {if (inputStream != null){try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}3、緩存文件
| getCacheDir | 獲取緩存路徑 |
| getFilesDir() | 獲取緩存的絕對路徑 |
File.createTempFile()
public File getTempFile(Context context, String url) {File file;try {String fileName = Uri.parse(url).getLastPathSegment();file = File.createTempFile(fileName, null, context.getCacheDir());catch (IOException e) {// Error while creating file}return file; }四、手機外部存儲
讀寫文件權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> /* Checks if external storage is available for read and write */ public boolean isExternalStorageWritable() {String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state)) {return true;}return false; }/* Checks if external storage is available to at least read */ public boolean isExternalStorageReadable() {String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state) ||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {return true;}return false; }將文件以public形式保存在外部存儲
public File getAlbumStorageDir(String albumName) {// Get the directory for the user's public pictures directory.File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName);if (!file.mkdirs()) {Log.e(LOG_TAG, "Directory not created");}return file; }將文件以private形式保存在外部存儲中
public File getAlbumStorageDir(Context context, String albumName) {// Get the directory for the app's private pictures directory.File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), albumName);if (!file.mkdirs()) {Log.e(LOG_TAG, "Directory not created");}return file; }查詢剩余空間
可以通過File類的getFreeSpace()方法獲取剩余空間,getTotalSpace()方法獲取總大小
五、刪除文件
可以通過File對象的delete()方法刪除文件,如果文件保存在內部存儲,可以通過Context的deleteFile(fileName)方法刪除
六、Environment
1、getExternalStorageState():獲取外部存儲狀態
| MEDIA_MOUNTED | SD卡已經掛載,可用 |
| MEDIA_UNKNOWN | 不能識別SD卡 |
| MEDIA_MOUNTED_READ_ONLY | 只讀狀態 |
| MEDIA_UNMOUNTED | SD卡存在但是沒有掛載 |
| MEDIA_REMOVED | SD卡已經移除 |
| MEDIA_CHECKING | SD卡正在準備 |
| getExternalStorageDirectory() | 獲取外部存儲路徑 |
| getExternalStoragePublicDirectory() | 獲取public的外部路徑 |
| getExternalFilesDir() | 獲取私有的外部路徑 |
| getDataDirectory() | rom內存 |
七、使用SQLite數據庫
數據庫文件會存放在/data/data/<package name>/databases/目錄下
1、SQLiteOpenHelper
創建數據庫的輔助類
public class MySQLiteOpenHelper extends SQLiteOpenHelper {private static final String DB_NAME = "user.db";private static final int VERSION = 1;public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);//name:數據庫名稱,version:數據庫版本,factory:游標工廠}public MySQLiteOpenHelper(Context context) {super(context, DB_NAME, null, VERSION);}//數據庫創建@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("create table person (_id integer primary key autoincrement, " +"name char(10), phone char(20), money integer(20))");}//數據庫升級@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}@Overridepublic void onOpen(SQLiteDatabase db) {super.onOpen(db);} }數據庫SQLiteDatabase
常用的一些方法
| execSQL() | 執行SQL語句實現增刪操作 |
| Cursor rawQuery() | 執行sql語句查詢數據庫 |
| insert() | 往數據庫插入數據 |
| delete() | 從數據庫刪除數據 |
| update() | 更新數據庫 |
| query() | 查詢數據 |
| beginTransaction() | 開始事務 |
| setTransactionSuccessful() | 設置事務成功 |
| endTransaction() | 結束事務 |
查詢數據庫
db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);參數意義
| table | 表名 |
| columns | 查詢的字段 |
| selection | 查詢條件,對應sql語句的where條件 |
| selectionArgs | 填充查詢條件的占位符 |
| groupBy | 分組參數 |
| having | 分組條件 |
| orderBy | 排序,“字段名 desc/ ASC” |
| limit | 分頁查詢,“m,n”,m表示從第幾條開始查,n表示一個查詢多少條數據 |
游標Cursor
保存查詢數據庫的結果,原理有點像迭代器
| moveToNext() | 移動到下一個數據 |
| moveToFirst() | 移動到第一個數據 |
| moveToPrevious() | 移動到前一個數據 |
| moveToLast() | 移動到下一個數據 |
| getString() | 獲取String類型的值 |
| getInt() | 獲取int類型的值 |
| getColumnIndex() | 獲取列索引 |
| getColumnNames() | 獲取所有字段名字 |
| getCount() | 獲取數據的個數 |
事務Transaction
使用事務會大大提高批量處理的效率
try {//開啟事務db.beginTransaction();...........//設置事務執行成功db.setTransactionSuccessful(); } finally{//關閉事務//如果此時已經設置事務執行成功,則sql語句生效,否則不生效db.endTransaction(); }android的數據持久化方式分為五種:
數據存儲在開發中是使用最頻繁的,在這里主要介紹Android平臺中實現數據存儲的5種方式。
當面試官問道我們這個問題的時候,回答的思路一般是這樣的。
首先常見的持久化方式有五種:分別是:
1 使用SharedPreferences存儲數據;
2 文件存儲數據;xml,json
3 SQLite數據庫存儲數據;
4 使用ContentProvider存儲數據;
5 網絡存儲數據;
(然后抽取其中的一個分開講解)比如sqlite。
首先我們要講解。1。sqlite為什么要用 2. sqlite有那些特點 3 。我們項目中又如何的運用
第一個問題,我們什么時候要使用數據庫呢,那些條件,那些數據要使用呢,要條分縷析的吧這些東西講清楚,那我在這里有個總結了:
有三種情況下我們要使用sqlite。1。數據量不是特別大的時候,為什么呢,數據量特別大的時候,一般都是些圖片視頻,這些其實都是用文件存儲的,數據量比較小的時候,其實可以直接在代碼中寫死,比如寫一個static常量,來存儲這些內容。
2. 復雜關系型數據,當數據關系不是很復雜的時候,單一鍵值對關系,我么可以用,map來存儲,或者用sp
3.數據更新不是特別快,也不是特別慢的時候,特別快的時候,我們會要頻繁的update數據庫,需要消耗大量資源,我們可以直接從網絡上面獲取即可。
數據跟新特別嗎難道時候,同樣我們可以寫死。
接下來,就是數據庫的特點了。
數據庫的特點,我在這里截圖說明:
分別介紹這些數據庫的特點。
3. 最后我們要結合項目。
比如我們的sqlite,我這個應用中有這樣一個需求,做一個數據插入,有10萬條數據,我插入的時候第一次是300ms,后來,我用了下事務,時間到了26ms。
這就是我在這里用的。
也可以在sqlite的特性存儲的時候,拙自己項目中這里符合這樣的特點,就用了sqllite。
這就叫做結合項目。
總結
以上是生活随笔為你收集整理的Android数据存储与持久化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android SQLite数据库的详细
- 下一篇: Android多媒体开发