Android官方培訓課程學習(四): 資料儲存
主要包括:
- 儲存到Preferences,使用Shared Preferences檔案以Key-Value的方式儲存簡要的資訊。
- 儲存到檔案,儲存基本的檔案。
- 儲存到資料庫,使用SQLite資料庫讀寫資料。(暫無記錄)
儲存到Preference
獲取SharedPreference
我們可以通過以下兩種方法之一建立或者訪問shared preference 檔案:
- getSharedPreferences() — 如果需要多個通過名稱引數來區分的shared preference檔案, 名稱可以通過第一個引數來指定。可在app中通過任何一個Context 執行該方法。
Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE);
- getPreferences() — 當activity僅需要一個shared preference檔案時。因為該方法會檢索activity下預設的shared preference檔案,並不需要提供檔名稱。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
注意: 如果建立了一個MODE_WORLD_READABLE或者MODE_WORLD_WRITEABLE 模式的shared preference檔案,則其他任何app均可通過檔名訪問該檔案。
寫Shared Preference
- 為了寫shared preferences檔案,需要通過執行edit()建立一個 SharedPreferences.Editor
- 通過類似putInt()與putString()等方法傳遞keys與values,接著通過commit() 提交改變
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.commit();
讀Shared Preference
為了從shared preference中讀取資料,可以通過類似於 getInt() 及 getString()等方法來讀取。在那些方法裡面傳遞我們想要獲取的value對應的key,並提供一個預設的value作為查詢的key不存在時函式的返回值。如下:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.string.saved_high_score), default);
儲存到檔案
儲存在內部還是外部
所有的Android裝置均有兩個檔案儲存區域:”internal” 與 “external” 。 這兩個名稱來自於早先的Android系統,當時大多裝置都內建了不可變的記憶體(internal storage)及一個類似於SD card(external storage)這樣的可解除安裝的儲存部件。之後有一些裝置將”internal” 與 “external” 都做成了不可解除安裝的內建儲存,雖然如此,但是這一整塊還是從邏輯上有被劃分為”internal”與”external”的。只是現在不再以是否可解除安裝進行區分了。 下面列出了兩者的區別:
- Internal storage:
- 總是可用的
- 這裡的檔案預設只能被我們的app所訪問。
- 當使用者解除安裝app的時候,系統會把internal內該app相關的檔案都清除乾淨。
- Internal是我們在想確保不被使用者與其他app所訪問的最佳儲存區域。
- External storage:
- 並不總是可用的,因為使用者有時會通過USB儲存模式掛載外部儲存器,當取下掛載的這部分後,就無法對其進行訪問了。
- 是大家都可以訪問的,因此儲存在這裡的檔案可能被其他程式訪問。
- 當使用者解除安裝我們的app時,系統僅僅會刪除external根目錄(getExternalFilesDir())下的相關檔案。
- External是在不需要嚴格的訪問許可權並且希望這些檔案能夠被其他app所共享或者是允許使用者通過電腦訪問時的最佳儲存區域。
Tip: 儘管app是預設被安裝到internal storage的,我們還是可以通過在程式的manifest檔案中宣告
android:installLocation
屬性來指定程式安裝到external storage。
獲取External儲存的許可權
為了寫資料到external storage, 必須在你manifest檔案中請求WRITE_EXTERNAL_STORAGE許可權:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
Caution:目前,所有的apps都可以在不指定某個專門的許可權下做讀external
storage的動作。但這在以後的安卓版本中會有所改變。如果我們的app只需要讀的許可權(不是寫), 那麼將需要宣告
READ_EXTERNAL_STORAGE 許可權。為了確保app能持續地正常工作,我們現在在編寫程式時就需要宣告讀許可權。
<manifest ...> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ... </manifest>
但是,如果我們的程式有宣告WRITE_EXTERNAL_STORAGE 許可權,那麼就預設有了讀的許可權。
對於internal storage,我們不需要宣告任何許可權,因為程式預設就有讀寫程式目錄下的檔案的許可權。
儲存到Internal Storage
當儲存檔案到internal storage時,可以通過執行下面兩個方法之一來獲取合適的目錄作為 FILE 的物件:
- getFilesDir() : 返回一個File,代表了我們app的internal目錄。
- getCacheDir() :返回一個File,代表了我們app的internal快取目錄。請確保這個目錄下的檔案能夠在一旦不再需要的時候馬上被刪除,並對其大小進行合理限制,例如1MB。系統的內部儲存空間不夠時,會自行選擇刪除快取檔案。
可以使用File() 構造器在那些目錄下建立一個新的檔案,如下:
File file = new File(context.getFilesDir(), filename);
同樣,也可以執行openFileOutput() 獲取一個 FileOutputStream 用於寫檔案到internal目錄。如下:
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
如果需要快取一些檔案,可以使用createTempFile()。例如:下面的方法從URL中抽取了一個檔名,然後再在程式的internal快取目錄下建立了一個以這個檔名命名的檔案。
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;
}
儲存檔案到External Storage
因為external storage可能是不可用的,比如遇到SD卡被拔出等情況時。因此在訪問之前應對其可用性進行檢查。我們可以通過執行 getExternalStorageState()來查詢external storage的狀態。若返回狀態為MEDIA_MOUNTED, 則可以讀寫。示例如下:
/* 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;
}
儘管external storage對於使用者與其他app是可修改的,我們可能會儲存下面兩種型別的檔案。
- Public files:這些檔案對與使用者與其他app來說是public的,當使用者解除安裝我們的app時,這些檔案應該保留。例如,那些被我們的app拍攝的圖片或者下載的檔案。
- Private files: 這些檔案完全被我們的app所私有,它們應該在app被解除安裝時刪除。儘管由於儲存在external storage,那些檔案從技術上而言可以被使用者與其他app所訪問,但實際上那些檔案對於其他app沒有任何意義。因此,當使用者解除安裝我們的app時,系統會刪除其下的private目錄。例如,那些被我們的app下載的快取檔案。
想要將檔案以public形式儲存在external storage中,請使用getExternalStoragePublicDirectory()方法來獲取一個 File 物件,該物件表示儲存在external storage的目錄。這個方法會需要帶有一個特定的引數來指定這些public的檔案型別,以便於與其他public檔案進行分類。引數型別包括DIRECTORY_MUSIC 或者 DIRECTORY_PICTURES. 如下:
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形式儲存在external storage中,可以通過執行getExternalFilesDir() 來獲取相應的目錄,並且傳遞一個指示檔案型別的引數。每一個以這種方式建立的目錄都會被新增到external storage封裝我們app目錄下的引數資料夾下(如下則是albumName)。這下面的檔案會在使用者解除安裝我們的app時被系統刪除。如下示例:
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;
}
如果剛開始的時候,沒有預定義的子目錄存放我們的檔案,可以在 getExternalFilesDir()方法中傳遞null. 它會返回app在external storage下的private的根目錄。
請記住,getExternalFilesDir() 方法會建立的目錄會在app被解除安裝時被系統刪除。如果我們的檔案想在app被刪除時仍然保留,請使用getExternalStoragePublicDirectory().
無論是使用 getExternalStoragePublicDirectory() 來儲存可以共享的檔案,還是使用 getExternalFilesDir() 來儲存那些對於我們的app來說是私有的檔案,有一點很重要,那就是要使用那些類似DIRECTORY_PICTURES 的API的常量。那些目錄型別引數可以確保那些檔案被系統正確的對待。例如,那些以DIRECTORY_RINGTONES 型別儲存的檔案就會被系統的media scanner認為是ringtone而不是音樂。
查詢剩餘空間
如果事先知道想要儲存的檔案大小,可以通過執行getFreeSpace() or getTotalSpace() 來判斷是否有足夠的空間來儲存檔案,從而避免發生IOException。那些方法提供了當前可用的空間還有儲存系統的總容量。
Note:並沒有強制要求在寫檔案之前去檢查剩餘容量。我們可以嘗試先做寫的動作,然後通過捕獲 IOException 。這種做法僅適合於事先並不知道想要寫的檔案的確切大小。
刪除檔案
在不需要使用某些檔案的時候應刪除它。刪除檔案最直接的方法是直接執行檔案的delete()方法。
myFile.delete();
如果檔案是儲存在internal storage,我們可以通過Context來訪問並通過執行deleteFile()進行刪除
myContext.deleteFile(fileName);
Note: 當使用者解除安裝我們的app時,android系統會刪除以下檔案:
- 所有儲存到internal storage的檔案。
- 所有使用getExternalFilesDir()方式儲存在external storage的檔案。
然而,通常來說,我們應該手動刪除所有通過 getCacheDir() 方式建立的快取檔案,以及那些不會再用到的檔案。
相關文章
- 學習Linux開發課程需要培訓嗎Linux
- 分享Cloudera大資料培訓課程的資訊Cloud大資料
- SAP標準培訓課程C4C10學習筆記(四)第四單元筆記
- 好程式設計師大資料培訓分享之hive儲存過程程式設計師大資料Hive儲存過程
- 參加UI培訓課程學什麼UI
- Python開發培訓課程都學哪些Python
- 雲端計算學習路線課程大綱資料:儲存基礎知識
- 綠盟科技資料安全培訓課程體系正式釋出
- FPGA/CPLD開發培訓課程FPGA
- oracle 儲存過程學習Oracle儲存過程
- 儲存過程學習教材儲存過程
- Oracle儲存過程學習Oracle儲存過程
- 整理了一份oracle資料庫培訓課程大綱Oracle資料庫
- 上海HP 儲存培訓歸來
- 國內首期:綠盟科技CCSC-資料安全培訓認證課程
- 上雲培訓課程:深入關係型資料庫服務RDS資料庫
- 【Mysql】Mysql儲存過程學習MySql儲存過程
- Python開發課程學習選擇培訓班原因是什麼?Python
- Oracle高階培訓 第5課 學習筆記Oracle筆記
- Oracle高階培訓 第6課 學習筆記Oracle筆記
- Oracle高階培訓 第7課 學習筆記Oracle筆記
- Hibernate學習(二)儲存資料
- Strata + Hadoop World 2天培訓課程Hadoop
- 第四講 資料儲存
- 重新學習Mysql資料庫3:Mysql儲存引擎與資料儲存原理MySql資料庫儲存引擎
- Android視訊學習(一):資料儲存與介面展示1Android
- go培訓課程都學什麼?go語言框架學習:xorm框架知識介紹Go框架ORM
- 資料庫儲存過程資料庫儲存過程
- 資料儲存(1):從資料儲存看人類文明-資料儲存器發展歷程
- Mysql 5.7儲存過程的學習MySql儲存過程
- 好程式設計師大資料培訓分享MySQL資料庫儲存引擎簡介程式設計師大資料MySql資料庫儲存引擎
- Apple Watch學習之路 資料儲存APP
- 資料庫學習 哈工大課程 第Ⅸ、Ⅹ講資料庫
- SAP Cloud for Customer 標準培訓課程Cloud
- Oracle資料倉儲高階課程Oracle
- MySql資料庫——儲存過程MySql資料庫儲存過程
- 儲存過程返回資料集儲存過程
- PLSQL學習-【7儲存過程、函式】SQL儲存過程函式