android數據存儲的途徑

譯自android.com

安卓為你是實現持久化數據提供了幾種選擇。具體的方案選擇取決于你的特定需要,比如存儲的數據是應用私有的還是對其他應用程序也是可見的,存儲你的數據需要多大的空間。

你存儲數據的選擇如下:

Shared Preferences

以鍵值對的形式保持私有的原始數據

Internal Storage

在設備的內存內保存私有的數據

External Storage

在外部存儲器保存公開的數據

SQLite Databases

在私有化的表中保存具備結構的數據

Network Connection

將數據保存在你的個人的網絡服務器

安卓通過content provider為你提供了一種向其他應用暴露你的隱私數據的方案。content provider是一個可以選擇實現的幫助你暴露你的應用數據的讀寫權限的組件,是一個subject to whatever restrictions you want to impose.

Using Shared Preferences

SharedPreferences這個類提供了一個允許你以保存和索取鍵值對類型的私密數據的框架。你可以使用SharedPreferences保存任何私密數據,比如布爾類型、浮點型、整型、長整型和字符串數據。這些數據會一直被持久化保存在整個用戶期間(即使你的應用進程已經被殺死)

為了獲得一個SharedPreferences對象,你可以使用下面任何一種方法:

1、getSharedPreferences()使用這個方法,你可以通過指定文件的名字獲得一個特定的配置文件(這種情況下,應用內會存在多個不同名字的配置文件)

2、getPreferences()使用這個方法如果你只需要為你的activity獲得唯一一個配置文件的對象。

你可以通過以下的步驟將數據寫進文件:

1、調用edit()這個方法獲取一個SharedPreferences.Editor.對象

2、通過諸如putBoolean()andputString()的方法添加數據

3、使用commit()方法提交數據

下面是一個具體的例子

publicclassCalcextendsActivity{

publicstaticfinalStringPREFS_NAME="MyPrefsFile";

@Override

protectedvoidonCreate(Bundlestate){

super.onCreate(state);

...

//?Restore?preferences

SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);

booleansilent=settings.getBoolean("silentMode",false);

setSilent(silent);

}

@Override

protectedvoidonStop(){

super.onStop();

//?We?need?an?Editor?object?to?make?preference?changes.

//?All?objects?are?from?android.context.Context

SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);

SharedPreferences.Editoreditor=settings.edit();

editor.putBoolean("silentMode",mSilentMode);

//?Commit?the?edits!

editor.commit();

}

}

Using the Internal Storage

你可以直接直接將數據保存在設備的內部存儲器。默認的情況下,保存在內部存儲設備的文件是隱秘的,即只有你自己的應用可以使用,其他應用,包括用戶沒有權限讀寫這些文件。當你的應用被卸載的時候,這些文件也會被移除。

你可以通過以下步驟創建一個文件并將其保存到你的內部存儲設備:

1、調用openFileOutput()這個方法,并將文件的名字以及操作的模式作為參數傳入,這個方法會返回一個FileOutputStream

2、利用write()將數據寫入文件

3、利用close()這個方法關閉輸入流

例如:

StringFILENAME="hello_file";

Stringstring="hello?world!";

FileOutputStreamfos=openFileOutput(FILENAME,Context.MODE_PRIVATE);

fos.write(string.getBytes());

fos.close();

MODE_PRIVATE將會創建一個文件(或者取代原來的同名文件),并且文件只有應用本書可以操作。其他有效的操作模式包括:MODE_APPEND,MODE_WORLD_READABLE, andMODE_WORLD_WRITEABLE

你可以通過以下步驟讀取內部存儲的文件數據:

1、調用openFileInput()方法并將文件名字作為參數傳入。這個方法會返回一個FileInputStream.

2、利用read()按字節讀取文件中的內容

3、利用close()關閉輸出流

Tip:If you want to save a static file in your application at compile time, save the file in your projectres/raw/directory. You can open it withopenRawResource(), passing theR.raw.resource ID. This method returns anInputStreamthat you can use to read the file (but you cannot write to the original file).

Saving cache files

如果你只是想保存臨時文件而并不是將數據持久化保存,你可以使用getCacheDir()的方法打開一個目錄,這是一個保存你的應用的臨時的緩存文件的目錄。

當你的設備的內部存儲容量不足的時候,安卓系統會自動的刪除這些緩存文件以便于回收空間。盡管如此,你不應該依賴于系統的自動回收功能,你應該自己控制這些緩存文件并維持一個合理的內存占用顯示,比如1mb。當你的應用被卸載的時候,這些文件就會被移除。

Other useful methods

getFilesDir()

獲取內部文件保存的絕對路徑

getDir()

在內部存儲系統中創建(存在的時候就直接打開)一個目錄

deleteFile()

刪除保存在內部文件系統的文件

fileList()

返回當前應用保存的文件

Using the External Storage

每一個安卓設備都支持外部存儲器,因此你可以用來保存你的文件。這可以是一個可移除的存儲器(比如sd卡),也可以是內置的(不可移除)存儲器。存儲在外部存儲器的文件是全局可讀的并且用戶可以修改這些文件當他們通過usb大容量數據與電腦連接的時候。

Caution:External storage can become unavailable if the user mounts the external storage on a computer or removes the media, and there's no security enforced upon files you save to the external storage. All applications can read and write files placed on the external storage and the user can remove them.

為了讀寫外部存儲設備的文件,你的應用需要獲得這些權限:READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE

...

在你使用外部存儲設備的時候,你應該調用方法檢測外部存儲設備是否可用。外部存儲設備有可能正被掛載到電腦、缺失、只讀或者其他的狀態,例如:

/*?Checks?if?external?storage?is?available?for?read?and?write?*/

publicbooleanisExternalStorageWritable(){

Stringstate=Environment.getExternalStorageState();

if(Environment.MEDIA_MOUNTED.equals(state)){

returntrue;

}

returnfalse;

}

/*?Checks?if?external?storage?is?available?to?at?least?read?*/

publicbooleanisExternalStorageReadable(){

Stringstate=Environment.getExternalStorageState();

if(Environment.MEDIA_MOUNTED.equals(state)||

Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){

returntrue;

}

returnfalse;

}

一般情況下,用戶能夠通過你的應用打開的文件應該被存儲在一個公共的路徑下并且其他應用可以訪問,并且用戶可以輕易的在設備上拷貝這些文件。當你這樣做的時候,你應該使用任意一個共享的目錄,比如:Music/,Pictures/, andRingtones/.

為了獲得一個合適的公共目錄的file對象,你可以調用getExternalStoragePublicDirectory()這個方法并將路徑的類型作為參數傳入,比如DIRECTORY_MUSIC,DIRECTORY_PICTURES,DIRECTORY_RINGTONES或者其他。通過將文件保存在直接的媒體類型的目錄內,系統的多媒體掃描器可以將你的文件進行合適的分類。比如:

publicFilegetAlbumStorageDir(StringalbumName){

//?Get?the?directory?for?the?user's?public?pictures?directory.

Filefile=newFile(Environment.getExternalStoragePublicDirectory(

Environment.DIRECTORY_PICTURES),albumName);

if(!file.mkdirs()){

Log.e(LOG_TAG,"Directory?not?created");

}

returnfile;

}

Saving files that are app-private

如果你正在處理一些文件你并不打算向其他應用程序公開,你應該通過調用方法getExternalFilesDir().使用外部存儲器中的隱私目錄。這個方法也可以指定一個類型參數作為子目錄。如果你并不需要一個指定的路徑,你可以傳一個空值獲取你應用的隱私目錄的根目錄。

從安卓4.4開始,讀寫本應用的隱私目錄并不需要提供READ_EXTERNAL_STORAGEorWRITE_EXTERNAL_STORAGE這兩個權限,所以你可以通過添加maxSdkVersion這個屬性聲明只有在低版本的系統中才需要加入權限:

android:maxSdkVersion="18"/>

...

Note:When the user uninstalls your application, this directory and all its contents are deleted. Also, the system media scanner does not read files in these directories, so they are not accessible from theMediaStorecontent provider. As such, youshould not use these directoriesfor media that ultimately belongs to the user, such as photos captured or edited with your app, or music the user has purchased with your app—those files should besaved in the public directories.

有時候,設備已經從內部存儲器中分割一部分內存作為外部存儲并且同時又提供了一個sd卡的拓展卡槽。當這樣的設備搭載的系統低于安卓4.3(包括4.3)的時候,方法getExternalFilesDir()只提供了讀寫內部存儲的權限并且你的應用并不可以對sd卡進行讀寫操作。然而,從安卓4.4開始,你可以通過調用方法getExternalFilesDir()獲取內部和外部的讀寫權限,這時候方法會返回一個包含兩個路徑的file數組。第一個數組元素是最主要的外部存儲設備的路徑,你應該使用這一個路徑除非它的存儲空間已滿或者不可用。如果你想要在系統為4.3及以下的設備上獲取兩個路徑的權限。你可以使用支持庫的靜態方法ContextCompat.getExternalFilesDirs()。這個方法會返回一個file的數組,但是通常情況下,在4.3及以下的系統只會得到一個元素。

CautionAlthough the directories provided bygetExternalFilesDir()andgetExternalFilesDirs()are not accessible by theMediaStorecontent provider, other apps with theREAD_EXTERNAL_STORAGEpermission can access all files on the external storage, including these. If you need to completely restrict access for your files, you should instead write your files to theinternal storage.

Saving cache files

你可以調用方法getExternalCacheDir()獲得內部存儲器的一個用于存儲緩存文件的file對象。如果你的應用被卸載的話,這寫文件也會被移除。

與上面提及到的方法ContextCompat.getExternalFilesDirs()相類似,你可以獲得第二存儲器中的緩存目錄通過調用方法ContextCompat.getExternalCacheDirs()。

Tip:To preserve file space and maintain your app's performance, it's important that you carefully manage your cache files and remove those that aren't needed anymore throughout your app's lifecycle.

Using Databases

安卓提供了對sqlite數據庫的全部支持。并且通過你創建的數據庫的名字可以在應用的每一個類中使用,但是不會超出你的應用。

推薦你使用繼承SQLiteOpenHelper并重寫onCreate()這個方法來創建一個新的數據庫。在onCreate()方法中你可以執行一個sqlite命令在數據庫中創建一張表,例如:

publicclassDictionaryOpenHelperextendsSQLiteOpenHelper{

privatestaticfinalintDATABASE_VERSION=2;

privatestaticfinalStringDICTIONARY_TABLE_NAME="dictionary";

privatestaticfinalStringDICTIONARY_TABLE_CREATE=

"CREATE?TABLE?"+DICTIONARY_TABLE_NAME+"?("+

KEY_WORD+"?TEXT,?"+

KEY_DEFINITION+"?TEXT);";

DictionaryOpenHelper(Contextcontext){

super(context,DATABASE_NAME,null,DATABASE_VERSION);

}

@Override

publicvoidonCreate(SQLiteDatabasedb){

db.execSQL(DICTIONARY_TABLE_CREATE);

}

}

你可以獲得一個你已經實現的SQLiteOpenHelper的實例通過你已經定義好的構造器。你可以調用getWritableDatabase()andgetReadableDatabase()這兩個方法分別獲取可讀和可寫的數據庫對象。

你可以通過調用SQLiteDatabasequery()方法執行sqlite 的查詢操作。query()方法樂意接受多個參數,包括要查詢的表的名字、要查詢的列名、分組列名等。對于那些復雜的查詢操作,比如需要列的同義名的,你可以使用SQLiteQueryBuilderSQLiteQueryBuilder,它可以提供多種便捷的方法執行查詢操作。

每一個sqlite的查詢操作會返回一個指向所有查詢到的行數據的指針。你可以利用這個指針實現查詢結果的導航并且讀取相關的行列信息。

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

推薦閱讀更多精彩內容