本篇文章會幫助你們快速瞭解Android中各類數據存儲機制的應用場景以及基本使用方法,力求在頭腦中創建一個「目錄」。有了這個目錄,具體使用細節在實際應用時再查詢文檔便可獲得。android
0. 概述數據庫
Android爲咱們提供瞭如下存儲機制:緩存
Shared Preferences: 以鍵-值對方式存儲應用私有的原始類型數據。服務器
Internal Storage(內部存儲): 存儲應用私有數據於設備自己的存儲空間中網絡
External Storage(外部存儲): 將公共數據存儲於外部存儲(如SD卡)中ide
SQLite Databases(SQLite數據庫): 將結構化數據存儲於私有數據庫中ui
Network Connection: 將數據存儲在你的網絡服務器中spa
在以上幾種數據存儲方式中,咱們能夠根據實際需求進行靈活選擇。好比,「數據是本應用私有的仍是與其餘應用共享」、「要存儲的數據大概須要多少存儲空間」等都是咱們在選擇具體的數據存儲機制時所要考慮的問題。下面咱們來一塊兒看一下這幾種存儲機制的應用場景和基本使用方法。code
1. 使用Shared Preferences
這種存儲方式用於存儲原始類型數據,包括boolean、int、long、float、double、String等。具體的存儲方式是鍵-值對,若咱們不主動刪除,這些數據會一直存在。
根據以上介紹,咱們很容易得出Shared Preferences適合存儲的數據有:
小遊戲的歷史最高分(整型數據);
用戶偏好設置:是否只在wifi時才加載圖片(boolean型)、是否開啓夜間模式(boolean型);
全部可以用原始類型所表示的用戶數據...
要使用Shared Preferences,咱們首先要獲取一個SharedPreference對象,要獲取這個對象有兩種方法:
getSharedPreferences()
- :使用這個方法能夠爲每一個數據文件指定一個文件名。
getPreferences()
-當你的Activity只須要一個數據文件來保存用戶數據時,這個方法就是你的菜。
在經過以上兩種方式之一獲取到一個SharedPreferences對象後,咱們就能夠開始向其中寫如用戶數據了,具體步驟以下:
調用edit()方法得到一個SharedPreferences.Editor對象
經過putBoolean()
,putDouble()
方法向其中添加鍵-值對
調用commit()進行提交
只需三步,咱們就成功地把用戶數據存起來啦。那麼當咱們想再此獲取已保存的數據時,該怎麼作呢?很簡單:只須要獲得一個SharedPreferences後調用 getBoolean(),getBoolean()
等方法便可。
咱們來看一下來自Android Developer的示例代碼:
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
@Override
protected void onCreate(Bundle state){
super.onCreate(state);
. . .
//從preferences文件中讀取以前咱們保存的數據
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
@Override
protected void onStop(){
super.onStop();
// 保存用戶數據
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// 提交後對用戶數據的保存才生效
editor.commit();
}
}
使用這種方式會把數據存到應用私有的存儲空間中,其餘應用無權訪問這個存儲空間,而且當用戶卸載你的應用時,這些數據也會被刪除掉。由此咱們能夠知道當咱們要保存的數據只用於本應用時,而且但願它同本應用「同生共死」時,就可使用內部存儲。
要建立一個應用私有文件用於數據保存也只須要三步:
調用 openFileOutput()
獲得一個FileOutputStream(文件輸出流)對象
使用write()向其中寫入數據
調用write()關閉以前打開的文件輸出流
示例以下:
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
上面方法中的MODE_PRIVATE
參數的意思就是這個數據文件是本應用私有的,其餘應用不能夠訪問。
要從內部存儲的文件中讀取數據也很簡單,只需三步:
調用並提供給它咱們要讀取的文件的名稱,它會返回給咱們一個FileInputStream
對象
使用read()方法從中讀取數據
調用close()方法關閉以前打開的文件輸入流
有些時候咱們想要存儲一些臨時數據在應用的私有存儲空間中,這時候咱們能夠經過 getCacheDir()
方法獲得應用用於保存臨時緩存文件的內部目錄。存儲在這個目錄下的文件有個特色:當內部存儲空間不足時,系統會自動刪除一些這個文件夾下的文件。固然,剛靠譜的方式是咱們本身維護這個文件夾下的文件。一樣,這個文件夾下的文件在應用被卸載時候也會被刪除。
關於使用內部存儲更詳細的介紹請參考文末」參考資料「部分給出的連接。
Android中的外部存儲一般指SD卡,存儲於外部存儲的文件一般對於各個應用來講是共享的。顯然,當咱們但願保存的數據被系統中的各個應用共享時,就能夠考慮使用外部存儲;另外一方面,因爲手機的內部存儲廣泛較外部存儲小,咱們也應該把一些比較大的數據文件放於外部存儲中。存儲於外部存儲中的數據文件不會隨着應用的卸載而被刪除。
要讀寫外部存儲中的文件,咱們首先須要在AndroidManifest.xml文件中聲明以下權限:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
這樣既能夠了嗎?顯然不行,咱們在使用外部存儲前首先要確保用戶的手機中存在可用的外部存儲(萬一用戶的手機裏壓根沒有SD卡呢...)。實現這個很簡單,請看官方給出的示例代碼:
/* 檢查是否能夠讀寫外部存儲 */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* 檢查是否只可以讀而不能寫外部存儲 */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
對於一些公共的音樂、圖片或是鈴聲文件,咱們能夠將它們分別存儲於外部存儲的 Music/
, Pictures/
,Ringtones/
文件夾中。要獲得表明上述公共文件夾的File對象,只需調用getExternalStoragePublicDirectory()方法,並傳入一個參數指明咱們具體想訪問哪一個文件夾(DIRECTORY_MUSIC
, DIRECTORY_PICTURES
, DIRECTORY_RINGTONES
等)。
好比下面的方法在公共圖片目錄中建立了一個用於保存新相冊的文件夾:
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;
}
那麼當咱們僅僅是由於手機內部存儲不足而把數據存於外部存儲,有沒有辦法讓這些數據是本應用私有的呢?答案是確定的。咱們只需調用getExternalFilesDir()方法來獲取一個外部存儲中的私有存儲目錄。位於這個目錄中的數據文件會隨着應用的卸載而被刪除,畢竟它們只對該應用自己有意義。
從Android 4.4(API 19)開始,讀寫這個位於外部存儲中的應用私有目錄無需加上權限聲明。因此咱們能夠在AndroidManifest.xml中添加maxSdkVersion
屬性來講明這一權限只在Android 4.4以前才須要。
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest>
同內部存儲同樣,外部存儲中也有個專門用來保存臨時文件的緩存文件夾。要獲取表明本應用的緩存文件夾的File對象,只需調用getExternalCacheDir()方法,當用戶卸載引用時,這些文件也會被自動刪除。
前面咱們提到過,SQLite數據庫用來存儲結構化數據,所謂機構化數據就是有着固定結構的數據。好比成績表、工資表等等就是自然的適合用數據庫存儲的結構化數據。
Android推薦的訪問SQLite數據庫的方式是建立一個SQLiteOpenHelper的子類並重寫 onCreate()
方法,在這個方法中執行建立數據庫表的SQLite命令,好比如下代碼:
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DICTIONARY_TABLE_NAME = "dictionary";
private static final String DICTIONARY_TABLE_CREATE =
"CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
KEY_WORD + " TEXT, " +
KEY_DEFINITION + " TEXT);";
DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DICTIONARY_TABLE_CREATE);
}
}
而後咱們就能夠獲取以上 SQLiteOpenHelper
子類的實例開始對數據庫進行操做了。咱們能夠分別調用 getReadableDatabase()
和getWritableDatabase()方法來對數據庫進行讀操做和寫操做。這倆方法都會返回一個 SQLiteDatabase
對象,這個對象提供了查改增刪等數據庫常規操做方法。
要對SQLite數據庫執行查詢操做,能夠調用 SQLiteDatabase
query()
方法。對於複雜查詢操做,則使用SQLiteQueryBuilder是個更好的選擇。
每一個SQLite查詢操做都會返回一個指向了「符合查詢條件的全部行"的Cursor對象。關於Android中使用SQLite更加詳細的介紹,你們能夠參考文末給出的連接。
Android Developer: https://developer.android.com/guide/topics/data/data-storage.html(牆內用戶請看這裏:http://hukai.me/android-training-course-in-chinese/basics/data-storage/index.html)
Android中SQLite的使用:http://www.cnblogs.com/Excellent/archive/2011/11/19/2254888.html