前言
之前一直在講AndroidUI的內容,但是還沒有完結,之後會慢慢補充。今天講講其他的,關於資料持久化的內容。對於一個應用程式而言,不可避免的要能夠對資料進行儲存,Android程式也不例外。而在Android中,提供了幾種實現資料持久化的方法。後面會分別介紹。
在Android中,可以使用幾種方式實現資料持久化:
- Shared Preferences:共用參數形式,一種以Key-Value的索引值對形式儲存資料的方式,Android內建的,一般應用的配置資訊,推薦使用此種方式儲存。
- Internal Storage:使用Android裝置內建的記憶體儲存資料。
- External Storage:使用外部存放裝置儲存資料,一般是指Sdcard。
- SQLite Databases:以SQLite資料庫儲存結構化的資料。
- Network Connection:使用基於網路的服務擷取資料,可以參見另外一篇部落格:Android--Apache HttpClient。
後面幾天會分別介紹以上幾種方式實現的資料持久化,對於SharedPreferences而言,之前寫過一篇部落格,但是自己不是很滿意,之後有時間會再重新寫一份關於SharedPreferences的部落格,有興趣的朋友可以先去看看,Android--使用SharedPreferences。今天先介紹Internal Storage以及External Storage。
Internal Storage
內部儲存,在Android中,開發人員可以直接使用裝置的內部儲存空間中儲存檔案,預設情況下,以這種方式儲存的和資料是只能被當前程式訪問,在其他程式中是無法訪問到的,而當使用者卸載該程式的時候,這些檔案也會隨之被刪除。
使用內部儲存儲存資料的方式,基本上也是先獲得一個檔案的輸出資料流,然後以write()的方式把待寫入的資訊寫入到這個輸出資料流中,最後關閉流即可,這些都是Java中IO流的操作。具體步驟如下:
- 使用Context.openFileOutput()方法擷取到一個FileOutputStream對象。
- 把待寫入的內容通過write()方法寫入到FileOutputStream對象中。
- 最後使用close()關閉流。
上面介紹的Context.openFileOutput()方法有兩個重載函數,它們的簽名分別是:
- FileOutputStream openFileOutput(String name):以MODE_PRIVATE的模式開啟name檔案。
- FileOutputStream openFileOutput(String name,int mode):以mode的模式開啟name檔案。
上面第二個重載函數中,mode為一個int類型的資料,這個一般使用Context對象中設定好的常量參數,有如下幾個:
- MODE_APPEND:以追加的方式開啟一個檔案,使用此模式寫入的內容均追加在原本內容的後面。
- MODE_PRIVATE:私人模式(預設),如果檔案已經存在會重新建立並替換原檔案,如果不存在直接建立。
- MODE_WORLD_READABLE:以唯讀方式開啟檔案。
- MODE_WORLD_WRITEABLE:以唯寫的方式開啟檔案。
還有幾個方法需要特別注意一下,這幾個方法對於檔案關係提供了更好的支援,配合上面介紹的方式,就可以對檔案的資料進行常規的CRUD操作(增刪改查),方法如下:
- File getFIlesDir():擷取檔案系統的絕對路徑。
- boolean deleteFile(String name):刪除一個指定檔案名稱為name的檔案。
- String[] fileList():當前應用內部儲存路徑下的所有檔案名稱。
講了這麼多,下面通過一個簡單的Demo來示範一下上面提到的內容。在這個Demo中,指定檔案名稱和內容,既可建立檔案,並且可以對其內容進行追加、修改、刪除、查詢等操作。
="match_parent"="match_parent"="vertical" > <="match_parent"="wrap_content"="file name:" /> <="@+id/etInternalFilename"="match_parent"="wrap_content" /> <="match_parent"="wrap_content"="Content:" /> <="@+id/etInternalContent"="match_parent"="wrap_content" /> <="match_parent"="wrap_content"="horizontal" > <="@+id/btnInternalSave"="wrap_content"="wrap_content"="save" /> <="@+id/btnInternalDelete"="wrap_content"="wrap_content"="delete" /> <="@+id/btnInternalAppend"="wrap_content"="wrap_content"="append" /> <="@+id/btnInternalQuery"="wrap_content"="wrap_content"="query" /> </LinearLayout><!-- 以一個ListView的形式展示當前程式內部儲存路徑下的所有檔案 --> <="@+id/lvInternalData"="match_parent"="fill_parent" > </ListView></LinearLayout>View Code
內部儲存的操作類,對其實現CRUD操作:
.context = save(String filename, String content) File file = = String get(String filename) == [] data = [1024 len = -1 ((len = fis.read(data)) != -10 append(String filename, String content) = View Code
Activity代碼:
InternalStorageActivity = onItemClick(AdapterView<?> parent, View view, "1"=<String> adapter = (ArrayAdapter<String>== ===== = === , "儲存檔案成功", "儲存檔案失敗"== = === , "儲存內容追加成功", "檔案內容追加失敗"= = =<String> fileArray = ArrayAdapter<String>, "查詢檔案清單"= == , "刪除檔案成功"View Code
使用內部儲存的方式進行資料持久化,檔案的地址將儲存在/data/data/<package_name>/files/路徑下,上面建立了三個檔案,最後刪掉了一個,如果是使用的模擬器,可以直接在File Explorer中查看:
緩衝(cache)
既然提到了內部儲存,這裡再簡單的說說關於快取檔案(cache files)。cache files的操作與操作內部儲存中的檔案方式基本一致,只是擷取檔案的路徑有說不同。如果需要使用緩衝的方式進行資料持久話,那麼需要使用Context.getCacheDir()方法擷取檔案儲存的路徑。
對於快取檔案而言,當裝置內部記憶體儲存空間不足的時候,Android會有自動刪除的機制刪除這些快取檔案,用來恢複可用空間,所以對於快取檔案而言,內容一般最好控制在1MB之下,並且也不要存放重要的資料,因為很可能下次去取資料的時候,已經被Android系統自動清理了。
External Storage
使用外部儲存實現資料持久化,這裡的外部儲存一般就是指的是sdcard。使用sdcard儲存的資料,不限制只有本應用訪問,任何可以有訪問Sdcard許可權的應用均可以訪問,而Sdcard相對於裝置的內部儲存空間而言,會大很多,所以一般比較大的資料,均會存放在外部儲存中。
使用SdCard儲存資料的方式與內部儲存的方式基本一致,但是有三點需要注意的:
- 第一點,需要首先判斷是否存在可用的Sdcard,這個可以使用一個訪問裝置環境變數的類Environment進行判斷,這個類提供了一系列的靜態方法,用於擷取當前裝置的狀態,在這裡擷取是否存在有效Sdcard,使用的是Environment.getExternalStorageState()方法,返回的是一個字串資料,Environment封裝好了一些final對象進行匹配,除了Environment.MEDIA_MOUNTED外,其他均為有問題,所以只需要判斷是否是Environment.MEDIA_MOUNTED狀態即可。
- 第二點,既然轉向了Sdcard,那麼儲存的檔案路徑就需要相對變更,這裡可以使用Envir.getExternalStorageDirectory()方法擷取當Sdcard的根目錄,可以通過它訪問到相應的檔案。
- 第三點,需要賦予應用程式訪問Sdcard的許可權,Android的許可權控制尤為重點,在Android程式中,如果需要做一些越界的操作,均需要對其進行授權才可以訪問。在AndroidManifest.xml中添加代碼:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
因為訪問Sdcard的方式和訪問內部儲存的方式差不多,這裡就展示一個Save的方法,用於儲存檔案,其他CRUD操作,這裡就不再一一給出了。
saveToSdcard(String filename, String content) "main", "本裝置有儲存卡!"= = = View Code
而如果使用SdCard隱藏檔的話,存放的路徑在Sdcard的根目錄下,如果使用模擬器運行程式的話,建立的檔案在/mnt/sdcard/目錄下:
補充:對於現在市面上很多Android裝置,內建了一個大的儲存空間,一般是8GB或16GB,並且又支援了Sdcard擴充,對於這樣的裝置,使用Enviroment.getExternalStorageDirectory()方法只能擷取到裝置內建的儲存空間,對於另外擴充的Sdcard而言,需要修改路徑。