Android數據存儲實現的5大方式
發表時間:2020-10-19
發布人:葵宇科技
浏覽次數:41
數據存儲在開辟中(zhōng)是應用最頻繁的,在這裡重要介紹Android平台中(zhōng)實現數據存儲的5種方法,加倍體系具體的介紹了5種存儲的辦法和(hé)異同。
第一種: 應用SharedPreferences存儲數據
SharedPreferences是Android平台上一個(gè)輕量級的存儲類,主如(rú)果保存一些常用的設備比如(rú)窗口狀況,一般在Activity中(zhōng) 重載窗口狀況onSaveInstanceState保存一般應用SharedPreferences完成,它供給了Android平台慣例的Long長 整形、Int整形、String字符串型的保存。
它是什麼樣的處理方法呢(ne)? SharedPreferences類似以前Windows體系上的ini設備文(wén)件,然則它分為多種權限,可(kě)以全局共享拜訪,android123提示最終是以xml方法來保存,整體效力來看不是特其餘高,對于慣例的輕量級而言比SQLite要好不少(shǎo),如(rú)不雅真的存儲量不大年夜可(kě)以推敲本身定義文(wén)件格式。xml 處理時Dalvik會經由過程自帶底層的本地XML Parser解析,比如(rú)XMLpull方法,如(rú)許對于内存資(zī)本占用比較好。
它的本質是基于XML文(wén)件存儲key-value鍵值對數據,平日用來存儲一些簡單的設備信息。
其存儲地位在/data/data/<包名>/shared_prefs目次下(xià)。
SharedPreferences對象本身隻能獲取數據而不支撐存儲和(hé)修改,存儲修改是經由過程Editor對象實現。
實現SharedPreferences存儲的步調如(rú)下(xià):
一、根據Context獲取SharedPreferences對象
二、應用edit()辦法獲取Editor對象。
三、經由過程Editor對象存儲key-value鍵值對數據。
四、經由過程commit()辦法提交數據。
下(xià)面是示例代碼:
Java代碼
這段代碼履行過後,即在/data/data/com.test/shared_prefs目次下(xià)生成了一個(gè)SP.xml文(wén)件,一個(gè)應用可(kě)以創建多個(gè)如(rú)許的xml文(wén)件。
SharedPreferences對象與SQLite數據庫比拟,免除了創建數據庫,創建表,寫SQL語句等諸多操作,相對而言加倍便利,簡潔。然則SharedPreferences也有其自身缺點,比如(rú)其本能機能存儲boolean,int,float,long和(hé)String五種簡單的數據類型,比如(rú)其無法進行前提萌芽等。所以不論SharedPreferences的數據存儲操作是若何簡單,它也隻能是存儲方法的一種彌補,而無法完全替代如(rú)SQLite數據庫如(rú)許的其他數據存儲方法。
第二種: 内部文(wén)件存儲數據
關(guān)于文(wén)件存儲,Activity供給了openFileOutput()辦法可(kě)以用于把數據輸出到文(wén)件中(zhōng),具體的實現過程與在J2SE情況中(zhōng)保存數據到文(wén)件中(zhōng)是一樣的。
文(wén)件可(kě)用來存放大年夜量數據,如(rú)文(wén)本、圖片、音頻等。
默認地位:/data/data/<包>/files/***.***。
代碼示例:
Java代碼
openFileOutput()辦法的第一參數用于指定文(wén)件名稱,不克不及包含路(lù)徑分隔符“/” ,如(rú)不雅文(wén)件不存在,Android 會主動(dòng)創建它。
創建的文(wén)件保存在/data/data/<package name>/files目次,如(rú): /data/data/cn.itcast.action/files/itcast.txt ,經由過程點擊Eclipse菜單“Window”-“Show View”-“Other”,在對話窗口中(zhōng)展開android文(wén)件夾,選擇下(xià)面的File Explorer視圖,然後在File Explorer視圖中(zhōng)展開/data/data/<package name>/files目次就可(kě)以看到該文(wén)件。
openFileOutput()辦法的第二參數用于指定操作模式,有四種模式,分别為:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:為默認操作模式,代表該文(wén)件是私稀有據,隻能被應用本身拜訪,在該模式下(xià),寫入的内容會覆蓋原文(wén)件的内容,如(rú)不雅想把新寫入的内容追加到原文(wén)件中(zhōng)。可(kě)以應用Context.MODE_APPEND
Context.MODE_APPEND:模式會檢查文(wén)件是否存在,存在就往文(wén)件追加内容,不然就創建新文(wén)件。
Context.MODE_WORLD_READABLE和(hé)Context.MODE_WORLD_WRITEABLE用來控制其他應用是否有權限讀寫該文(wén)件。
MODE_WORLD_READABLE:表示當前文(wén)件可(kě)以被其他應用攫取;
MODE_WORLD_WRITEABLE:表示當前文(wén)件可(kě)以被其他應用寫入。
如(rú)不雅欲望文(wén)件被其他應用讀和(hé)寫,可(kě)以傳入: openFileOutput(“itcast.txt”, Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); android有一套本身的安然模型,當應用法度榜樣(.apk)在安裝時體系就會分派給他一個(gè)userid,當該應用要去拜訪其他資(zī)本好交手件的時刻,就須要userid匹配。默認情況下(xià),任何應用創建的文(wén)件,sharedpreferences,數據庫都應當是私有的(位于/data/data/<package name>/files),其他法度榜樣無法拜訪。
除非在創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,隻有如(rú)許其他法度榜樣才能精确拜訪。
攫取文(wén)件示例:
Java代碼
對于私有文(wén)件隻能被創建該文(wén)件的應用拜訪,如(rú)不雅欲望文(wén)件能被其他應用讀和(hé)寫,可(kě)以在創建文(wén)件時,指定Context.MODE_WORLD_READABLE和(hé)Context.MODE_WORLD_WRITEABLE權限。
Activity還供給了getCacheDir()和(hé)getFilesDir()辦法: getCacheDir()辦法用于獲取/data/data/<package name>/cache目次 getFilesDir()辦法用于獲取/data/data/<package name>/files目次。
第三種: 外部文(wén)件存儲數據
把文(wén)件存入SDCard:
應用Activity的openFileOutput()辦法保存文(wén)件,文(wén)件是存放在手機空間上,一般手機的存儲空間不是很大年夜,存放些小文(wén)件還行,如(rú)不雅要存放像視潑魅如(rú)許的大年夜文(wén)件,是弗成行的。對于像視潑魅如(rú)許的大年夜文(wén)件,我們可(kě)以把它存放在SDCard。
SDCard是幹什麼的?你(nǐ)可(kě)以把它看作是移動(dòng)硬盤或U盤。 在模仿器(qì)中(zhōng)應用SDCard,你(nǐ)須要先創建一張SDCard卡(當然不是真的SDCard,隻是鏡像文(wén)件)。
創建SDCard可(kě)以在Eclipse創建模仿器(qì)時伴随創建,也可(kě)以應用DOS敕令進行創建,如(rú)下(xià): 在Dos窗口中(zhōng)進入android SDK安裝路(lù)徑的tools目次,輸入以下(xià)敕令創建一張容量為2G的SDCard,文(wén)件後綴可(kě)以随便取,建議應用.img: mksdcard 2048M D:\AndroidTool\sdcard.img 在法度榜樣中(zhōng)拜訪SDCard,你(nǐ)須要申請拜訪SDCard的權限。
在AndroidManifest.xml中(zhōng)參加拜訪SDCard的權限如(rú)下(xià):
Java代碼
要往SDCard存放文(wén)件,法度榜樣必須先斷定手機是否裝有SDCard,并且可(kě)以進行讀寫。
留意:拜訪SDCard必須在AndroidManifest.xml中(zhōng)參加拜訪SDCard的權限。
Java代碼
Environment.getExternalStorageState()辦法用于獲取SDCard的狀況,如(rú)不雅手機裝有SDCard,并且可(kě)以進行讀寫,那麼辦法返回的狀況等于Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()辦法用于獲取SDCard的目次,當然要獲取SDCard的目次,你(nǐ)也可(kě)以如(rú)許寫:
Java代碼
第四種: SQLite數據庫存儲數據
SQLite是輕量級嵌入式數據庫引擎,它支撐 SQL 說話,并且隻應用很少(shǎo)的内存就有很好的機能。此外它照樣開源的,任何人都可(kě)以應用它。很多開源項目((Mozilla, PHP, Python)都應用了 SQLite.SQLite 由以下(xià)幾個(gè)組件構成:SQL 編譯器(qì)、内核、後端以及附件。SQLite 經由過程應用虛拟機和(hé)虛拟數據庫引擎(VDBE),使調試、修改和(hé)擴大 SQLite 的内核變得加倍便利。
特點:
面向資(zī)本竽暌剮限的設備,
沒有辦事器(qì)過程,
所稀有據存放在同一文(wén)件中(zhōng)跨平台,
可(kě)自由複制。
SQLite 内部構造:
[img]http://dl2.iteye.com/upload/attachment/0104/3780/9215176d-cf77-33f6-9b1c-885ea36d90f1.jpg
SQLite 根本上相符 SQL-92 标準,和(hé)其他的重要 SQL 數據庫沒什麼差别。它的長處就是高效,Android 運行時情況包含了完全的 SQLite。
SQLite 和(hé)其他數據庫最大年夜的不合就是對數據類型的支撐,創建一個(gè)表時,可(kě)以在 CREATE TABLE 語句中(zhōng)指定某列的數據類型,然則你(nǐ)可(kě)以把任何數據類型放入任何列中(zhōng)。當某個(gè)值插入數據庫時,SQLite 将檢查它的類型。如(rú)不雅該類型與接洽關(guān)系的列不匹配,則 SQLite 會測驗測驗将該值轉換成該列的類型。如(rú)不雅不克不及轉換,則該值将作為其本身具有的類型存儲。比如(rú)可(kě)以把一個(gè)字符串(String)放入 INTEGER 列。SQLite 稱這為“弱類型”(manifest typing.)。 此外,SQLite 不支撐一些标準的 SQL 功能,特别是外鍵束縛(FOREIGN KEY constrains),嵌套 transcaction 和(hé) RIGHT OUTER JOIN 和(hé) FULL OUTER JOIN, 還有一些 ALTER TABLE 功能。 除了上述功能外,SQLite 是一個(gè)完全的 SQL 體系,擁有完全的觸發器(qì),交易等等。
Android 集成了 SQLite 數據庫 Android 在運行時(run-time)集成了 SQLite,所以每個(gè) Android 應用法度榜樣都可(kě)以應用 SQLite 數據庫。
對于熟悉 SQL 的開辟人員來時,在 Android 開辟中(zhōng)應用 SQLite 相當簡單。然則,因為 JDBC 會消費太多的體系資(zī)本,所以 JDBC 對于手機這種内存受限設備來說并不合适。是以,Android 供給了一些新的 API 來應用 SQLite 數據庫,Android 開辟中(zhōng),法度榜樣員須要學應用這些 API。
數據庫存儲在 data/< 項目文(wén)件夾 >/databases/ 下(xià)。 Android 開辟中(zhōng)應用 SQLite 數據庫 Activites 可(kě)以經由過程 Content Provider 或者 Service 拜訪一個(gè)數據庫。
下(xià)面會具體講解如(rú)不雅創建數據庫,添加數據和(hé)萌芽數據庫。 創建數據庫 Android 不主動(dòng)供給數據庫。在 Android 應用法度榜樣中(zhōng)應用 SQLite,必須本身創建數據庫,然後創建表、索引,填充數據。
Android 供給了 SQLiteOpenHelper 贊助你(nǐ)創建一個(gè)數據庫,你(nǐ)隻要持續 SQLiteOpenHelper 類,就可(kě)以輕松的創建數據庫。SQLiteOpenHelper 類根據開辟應用法度榜樣的須要,封裝了創建和(hé)更新數據庫應用的邏輯。
SQLiteOpenHelper 的子(zǐ)類,至少(shǎo)須要實現三個(gè)辦法:
1 構造函數,調用父類 SQLiteOpenHelper 的構造函數。這個(gè)辦法須要四個(gè)參數:高低文(wén)情況(例如(rú),一個(gè) Activity),數據庫名字,一個(gè)可(kě)選的遊标工廠(平日是 Null),一個(gè)代表你(nǐ)正在應用的數據庫模型版本的┞符數。
2 onCreate()辦法,它須要一個(gè) SQLiteDatabase 對象作為參數,根據須要對這個(gè)對象填充表和(hé)初始化數據。
3 onUpgrage() 辦法,它須要三個(gè)參數,一個(gè) SQLiteDatabase 對象,一個(gè)舊的版本号和(hé)一個(gè)新的版本号,如(rú)許你(nǐ)就可(kě)以清跋假使何把一個(gè)數據庫大年夜舊的模型改變到新的模型。
下(xià)面示例代碼展示了若何持續 SQLiteOpenHelper 創建數據庫:
Java代碼
接下(xià)來評論辯論具體若何創建表、插入數據、删除表等等。調用 getReadableDatabase() 或 getWriteableDatabase() 辦法,你(nǐ)可(kě)以獲得 SQLiteDatabase 實例,具體調用那個(gè)辦法,取決于你(nǐ)是否須要改變數據庫的内容:
Java代碼
膳绫擎這段代碼會返回一個(gè) SQLiteDatabase 類的實例,應用這個(gè)對象,你(nǐ)就可(kě)以萌芽或者修改數據庫。 當你(nǐ)完成了對數據庫的操作(例如(rú)你(nǐ)的 Activity 已經封閉),須要調用 SQLiteDatabase 的 Close() 辦法來釋放掉落數據庫連接。 創建表和(hé)索引 為了創建表和(hé)索引,須要調用 SQLiteDatabase 的 execSQL() 辦法來履行 DDL 語句。如(rú)不雅沒有異常,這個(gè)辦法沒有返回值。
例如(rú),你(nǐ)可(kě)以履行如(rú)下(xià)代碼:
db.execSQL(“CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, value REAL);”);
這條語句會創建一個(gè)名為 mytable 的表,表有一個(gè)列名為 _id,并且是主鍵,這列的值是會主動(dòng)增長的┞符數(例如(rú),當你(nǐ)插入一行時,SQLite 會給這列主動(dòng)賦值),别的還有兩列:title( 字符 ) 和(hé) value( 浮點數 )。 SQLite 會主動(dòng)為主鍵列創建索引。 平日情況下(xià),第一次創建數據庫時創建了表和(hé)索引。
如(rú)不雅你(nǐ)不須要改變表的 schema,不須要删除表和(hé)索引 . 删除表和(hé)索引,須要應用 execSQL() 辦法調用 DROP INDEX 和(hé) DROP TABLE 語句。 給表添加數據 膳绫擎的代碼,已經創建了數據庫和(hé)表,如(rú)今須要給表添加數據。有兩種辦法可(kě)以給表添加數據。
像膳绫擎創建表一樣,你(nǐ)可(kě)以應用 execSQL() 辦法履行 INSERT, UPDATE, DELETE 等語句來更新表的數據。execSQL() 辦法實用于所有不返回結不雅的 SQL 語句。
例如(rú): db.execSQL(“INSERT INTO widgets (name, inventory)”+ “VALUES (‘Sprocket’, 5)”);
另一種辦法是應用 SQLiteDatabase 對象的 insert(), update(), delete() 辦法。這些辦法把 SQL 語句的一部分作為參數。
示例如(rú)下(xià):
Java代碼
update()辦法有四個(gè)參數,分别是表名,表示列名和(hé)值的 ContentValues 對象,可(kě)選的 WHERE 前提和(hé)可(kě)選的填充 WHERE 語句的字符串,這些字符串會調換 WHERE 前提中(zhōng)的“?”标記。
update() 根據前提,更新指定列的值,所以用 execSQL() 辦法可(kě)以達到同樣的目标。 WHERE 前提和(hé)其參數和(hé)用過的其他 SQL APIs 類似。
例如(rú):
String[] parms=new String[] {“this is a string”};
db.update(“widgets”, WordStrments, “name=?”, parms);
delete() 辦法的應用和(hé) update() 類似,應用表名,可(kě)選的 WHERE 前提和(hé)響應的填充 WHERE 前提的字符串。 萌芽數據庫 類似 INSERT, UPDATE, DELETE,有兩種辦法應用 SELECT 大年夜 SQLite 數據庫檢索數據。
1 .應用 rawQuery() 直接調用 SELECT 語句; 應用 query() 辦法構建一個(gè)萌芽。
Raw Queries 正如(rú) API 名字,rawQuery() 是最簡單的解決辦法。經由過程這個(gè)辦法你(nǐ)就可(kě)聲調用 SQL SELECT 語句。
例如(rú): Cursor c=db.rawQuery( “SELECT name FROM sqlite_master WHERE type=’table’ AND name=’mytable’”, null);
在膳绫擎例子(zǐ)中(zhōng),我們萌芽 SQLite 體系表(sqlite_master)檢查 table 表是否存在。返回值是一個(gè) cursor 對象,這個(gè)對象的辦法可(kě)以疊代萌芽結不雅。 如(rú)不雅萌芽是動(dòng)态的,應用這個(gè)辦法就會異常複雜。
例如(rú),當你(nǐ)須要萌芽的列在法度榜樣編譯的時刻不克不及肯定,這時刻應用 query() 辦法會便利很多。
Regular Queries query() 辦法用 SELECT 語句段構建萌芽。SELECT 語句内容作為 query() 辦法的參數,比如(rú):要萌芽的表名,要獲取的字段名,WHERE 前提,包含可(kě)選的地位參數,去替代 WHERE 前提中(zhōng)地位參數的值,GROUP BY 前提,HAVING 前提。 除了表名,其他參數可(kě)所以 null。所以,以前的代碼段可(kě)以可(kě)寫成:
String[] columns={“ID”, ”inventory”};
Java代碼
應用遊标
不管你(nǐ)若何履行萌芽,都邑返回一個(gè) Cursor,這是 Android 的 SQLite 數據庫遊标,
應用遊标,你(nǐ)可(kě)以:
經由過程應用 getCount() 辦法獲得結不雅集中(zhōng)有若幹記錄;
經由過程 moveToFirst(), moveToNext(), 和(hé) isAfterLast() 辦法遍曆所有記錄;
經由過程 getColumnNames() 獲得字段名;
經由過程 getColumnIndex() 轉換成字段号;
經由過程 getString(),getInt() 等辦法獲得給定字段當前記錄的值;
經由過程 requery() 辦法從新履行萌芽獲得遊标;
經由過程 close() 辦法釋放遊标資(zī)本;
例如(rú),下(xià)面代碼遍曆 mytable 表:
Java代碼
在 Android 中(zhōng)應用 SQLite 數據庫治理對象 在其他數據庫上作開辟,一般都應用對象來檢查和(hé)處理數據庫的内容,而不是僅僅應用數據庫的 API。
應用 Android 模仿器(qì),有兩種可(kě)供選擇的辦法來治理數據庫。
起首,模仿器(qì)綁定了 sqlite3 控制台法度榜樣,可(kě)以應用 adb shell 敕令來調用他。隻要你(nǐ)進入了模仿器(qì)的 shell,在數據庫的路(lù)徑履行 sqlite3 敕令就可(kě)以了。
數據庫文(wén)件一般存放在: /data/data/your.app.package/databases/your-db-name 如(rú)不雅你(nǐ)愛好應用更友愛的對象,你(nǐ)可(kě)以把數據庫拷貝到你(nǐ)的開辟機上,應用 SQLite-aware 客戶妒攀來操作它。如(rú)許的話,你(nǐ)在一個(gè)數據庫的拷貝上操作,如(rú)不雅你(nǐ)想要你(nǐ)的修改能反竽暌鈎到設備上,你(nǐ)須要把數據庫備份歸去。
把數據庫大年夜設備上考出來,你(nǐ)可(kě)以應用 adb pull 敕令(或者在 IDE 上做響應操作)。
存儲一個(gè)修悛改的數據庫到設備上,應用 adb push 敕令。 一個(gè)最便利的 SQLite 客戶端是 FireFox SQLite Manager 擴大,它可(kě)以跨所有平台應用。
下(xià)圖是SQLite Manager對象:
[img]http://dl2.iteye.com/upload/attachment/0104/3785/e6fabbe0-0372-34ff-b96b-8ddbfc322f89.jpg
如(rú)不雅你(nǐ)想要開辟 Android 應用法度榜樣,必定須要在 Android 上存儲數據,應用 SQLite 數據庫是一種異常好的選擇。
第五種: 收集存儲數據
前面介紹的幾種存儲都是将數據存儲在本地設備上,除此之外,還有一種存儲(獲取)數據的方法,經由過程收集來實現數據的存儲和(hé)獲取。
我們可(kě)聲調用WebService返回的數據或是解析HTTP協定實現收集數據交互。
具體須要熟悉java.net.*,Android.net.*這兩個(gè)包的内容,在這就不贅述了,請大年夜家參閱相幹文(wén)檔。
下(xià)面是一個(gè)經由過程地區名稱萌芽該地區的氣象預告,以POST發送的方法發送請求到webservicex.net站(zhàn)點,拜訪WebService.webservicex.net站(zhàn)點上供給萌芽氣象預告的辦事。
代碼如(rú)下(xià):
Java代碼
别忘記了在設備文(wén)件中(zhōng)設置拜訪收集權限:
Java代碼
第一種: 應用SharedPreferences存儲數據
SharedPreferences是Android平台上一個(gè)輕量級的存儲類,主如(rú)果保存一些常用的設備比如(rú)窗口狀況,一般在Activity中(zhōng) 重載窗口狀況onSaveInstanceState保存一般應用SharedPreferences完成,它供給了Android平台慣例的Long長 整形、Int整形、String字符串型的保存。
它是什麼樣的處理方法呢(ne)? SharedPreferences類似以前Windows體系上的ini設備文(wén)件,然則它分為多種權限,可(kě)以全局共享拜訪,android123提示最終是以xml方法來保存,整體效力來看不是特其餘高,對于慣例的輕量級而言比SQLite要好不少(shǎo),如(rú)不雅真的存儲量不大年夜可(kě)以推敲本身定義文(wén)件格式。xml 處理時Dalvik會經由過程自帶底層的本地XML Parser解析,比如(rú)XMLpull方法,如(rú)許對于内存資(zī)本占用比較好。
它的本質是基于XML文(wén)件存儲key-value鍵值對數據,平日用來存儲一些簡單的設備信息。
其存儲地位在/data/data/<包名>/shared_prefs目次下(xià)。
SharedPreferences對象本身隻能獲取數據而不支撐存儲和(hé)修改,存儲修改是經由過程Editor對象實現。
實現SharedPreferences存儲的步調如(rú)下(xià):
一、根據Context獲取SharedPreferences對象
二、應用edit()辦法獲取Editor對象。
三、經由過程Editor對象存儲key-value鍵值對數據。
四、經由過程commit()辦法提交數據。
下(xià)面是示例代碼:
Java代碼
- public class MainActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- //獲取SharedPreferences對象
- Context ctx = MainActivity.this;
- SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
- //存入數據
- Editor editor = sp.edit();
- editor.putString("STRING_KEY", "string");
- editor.putInt("INT_KEY", 0);
- editor.putBoolean("BOOLEAN_KEY", true);
- editor.commit();
- //返回STRING_KEY的值
- Log.d("SP", sp.getString("STRING_KEY", "none"));
- //如(rú)不雅NOT_EXIST不存在,則返回值為"none"
- Log.d("SP", sp.getString("NOT_EXIST", "none"));
- }
- }
這段代碼履行過後,即在/data/data/com.test/shared_prefs目次下(xià)生成了一個(gè)SP.xml文(wén)件,一個(gè)應用可(kě)以創建多個(gè)如(rú)許的xml文(wén)件。
SharedPreferences對象與SQLite數據庫比拟,免除了創建數據庫,創建表,寫SQL語句等諸多操作,相對而言加倍便利,簡潔。然則SharedPreferences也有其自身缺點,比如(rú)其本能機能存儲boolean,int,float,long和(hé)String五種簡單的數據類型,比如(rú)其無法進行前提萌芽等。所以不論SharedPreferences的數據存儲操作是若何簡單,它也隻能是存儲方法的一種彌補,而無法完全替代如(rú)SQLite數據庫如(rú)許的其他數據存儲方法。
第二種: 内部文(wén)件存儲數據
關(guān)于文(wén)件存儲,Activity供給了openFileOutput()辦法可(kě)以用于把數據輸出到文(wén)件中(zhōng),具體的實現過程與在J2SE情況中(zhōng)保存數據到文(wén)件中(zhōng)是一樣的。
文(wén)件可(kě)用來存放大年夜量數據,如(rú)文(wén)本、圖片、音頻等。
默認地位:/data/data/<包>/files/***.***。
代碼示例:
Java代碼
- public void save()
- {
- try {
- FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);
- outStream.write(text.getText().toString().getBytes());
- outStream.close();
- Toast.makeText(MyActivity.this,"Saved",Toast.LENGTH_LONG).show();
- } catch (FileNotFoundException e) {
- return;
- }
- catch (IOException e){
- return ;
- }
- }
openFileOutput()辦法的第一參數用于指定文(wén)件名稱,不克不及包含路(lù)徑分隔符“/” ,如(rú)不雅文(wén)件不存在,Android 會主動(dòng)創建它。
創建的文(wén)件保存在/data/data/<package name>/files目次,如(rú): /data/data/cn.itcast.action/files/itcast.txt ,經由過程點擊Eclipse菜單“Window”-“Show View”-“Other”,在對話窗口中(zhōng)展開android文(wén)件夾,選擇下(xià)面的File Explorer視圖,然後在File Explorer視圖中(zhōng)展開/data/data/<package name>/files目次就可(kě)以看到該文(wén)件。
openFileOutput()辦法的第二參數用于指定操作模式,有四種模式,分别為:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:為默認操作模式,代表該文(wén)件是私稀有據,隻能被應用本身拜訪,在該模式下(xià),寫入的内容會覆蓋原文(wén)件的内容,如(rú)不雅想把新寫入的内容追加到原文(wén)件中(zhōng)。可(kě)以應用Context.MODE_APPEND
Context.MODE_APPEND:模式會檢查文(wén)件是否存在,存在就往文(wén)件追加内容,不然就創建新文(wén)件。
Context.MODE_WORLD_READABLE和(hé)Context.MODE_WORLD_WRITEABLE用來控制其他應用是否有權限讀寫該文(wén)件。
MODE_WORLD_READABLE:表示當前文(wén)件可(kě)以被其他應用攫取;
MODE_WORLD_WRITEABLE:表示當前文(wén)件可(kě)以被其他應用寫入。
如(rú)不雅欲望文(wén)件被其他應用讀和(hé)寫,可(kě)以傳入: openFileOutput(“itcast.txt”, Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); android有一套本身的安然模型,當應用法度榜樣(.apk)在安裝時體系就會分派給他一個(gè)userid,當該應用要去拜訪其他資(zī)本好交手件的時刻,就須要userid匹配。默認情況下(xià),任何應用創建的文(wén)件,sharedpreferences,數據庫都應當是私有的(位于/data/data/<package name>/files),其他法度榜樣無法拜訪。
除非在創建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,隻有如(rú)許其他法度榜樣才能精确拜訪。
攫取文(wén)件示例:
Java代碼
- public void load()
- {
- try {
- FileInputStream inStream=this.openFileInput("a.txt");
- ByteArrayOutputStream stream=new ByteArrayOutputStream();
- byte[] buffer=new byte[1024];
- int length=-1;
- while((length=inStream.read(buffer))!=-1) {
- stream.write(buffer,0,length);
- }
- stream.close();
- inStream.close();
- text.setText(stream.toString());
- Toast.makeText(MyActivity.this,"Loaded",Toast.LENGTH_LONG).show();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- catch (IOException e){
- return ;
- }
- }
對于私有文(wén)件隻能被創建該文(wén)件的應用拜訪,如(rú)不雅欲望文(wén)件能被其他應用讀和(hé)寫,可(kě)以在創建文(wén)件時,指定Context.MODE_WORLD_READABLE和(hé)Context.MODE_WORLD_WRITEABLE權限。
Activity還供給了getCacheDir()和(hé)getFilesDir()辦法: getCacheDir()辦法用于獲取/data/data/<package name>/cache目次 getFilesDir()辦法用于獲取/data/data/<package name>/files目次。
第三種: 外部文(wén)件存儲數據
把文(wén)件存入SDCard:
應用Activity的openFileOutput()辦法保存文(wén)件,文(wén)件是存放在手機空間上,一般手機的存儲空間不是很大年夜,存放些小文(wén)件還行,如(rú)不雅要存放像視潑魅如(rú)許的大年夜文(wén)件,是弗成行的。對于像視潑魅如(rú)許的大年夜文(wén)件,我們可(kě)以把它存放在SDCard。
SDCard是幹什麼的?你(nǐ)可(kě)以把它看作是移動(dòng)硬盤或U盤。 在模仿器(qì)中(zhōng)應用SDCard,你(nǐ)須要先創建一張SDCard卡(當然不是真的SDCard,隻是鏡像文(wén)件)。
創建SDCard可(kě)以在Eclipse創建模仿器(qì)時伴随創建,也可(kě)以應用DOS敕令進行創建,如(rú)下(xià): 在Dos窗口中(zhōng)進入android SDK安裝路(lù)徑的tools目次,輸入以下(xià)敕令創建一張容量為2G的SDCard,文(wén)件後綴可(kě)以随便取,建議應用.img: mksdcard 2048M D:\AndroidTool\sdcard.img 在法度榜樣中(zhōng)拜訪SDCard,你(nǐ)須要申請拜訪SDCard的權限。
在AndroidManifest.xml中(zhōng)參加拜訪SDCard的權限如(rú)下(xià):
Java代碼
- <!-- 在SDCard中(zhōng)創建與删除文(wén)件權限 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <!-- 往SDCard寫入數據權限 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
要往SDCard存放文(wén)件,法度榜樣必須先斷定手機是否裝有SDCard,并且可(kě)以進行讀寫。
留意:拜訪SDCard必須在AndroidManifest.xml中(zhōng)參加拜訪SDCard的權限。
Java代碼
- if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
- File sdCardDir = Environment.getExternalStorageDirectory();//獲取SDCard目次
- File saveFile = new File(sdCardDir, “a.txt”);
- FileOutputStream outStream = new FileOutputStream(saveFile);
- outStream.write("test".getBytes());
- outStream.close();
- }
Environment.getExternalStorageState()辦法用于獲取SDCard的狀況,如(rú)不雅手機裝有SDCard,并且可(kě)以進行讀寫,那麼辦法返回的狀況等于Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()辦法用于獲取SDCard的目次,當然要獲取SDCard的目次,你(nǐ)也可(kě)以如(rú)許寫:
Java代碼
- File sdCardDir = new File("/sdcard"); //獲取SDCard目次
- File saveFile = new File(sdCardDir, "itcast.txt");
- //膳绫擎兩句代碼可(kě)以合成一句:
- File saveFile = new File("/sdcard/a.txt");
- FileOutputStream outStream = new FileOutputStream(saveFile);
- outStream.write("test".getBytes());
- outStream.close();
第四種: SQLite數據庫存儲數據
SQLite是輕量級嵌入式數據庫引擎,它支撐 SQL 說話,并且隻應用很少(shǎo)的内存就有很好的機能。此外它照樣開源的,任何人都可(kě)以應用它。很多開源項目((Mozilla, PHP, Python)都應用了 SQLite.SQLite 由以下(xià)幾個(gè)組件構成:SQL 編譯器(qì)、内核、後端以及附件。SQLite 經由過程應用虛拟機和(hé)虛拟數據庫引擎(VDBE),使調試、修改和(hé)擴大 SQLite 的内核變得加倍便利。
特點:
面向資(zī)本竽暌剮限的設備,
沒有辦事器(qì)過程,
所稀有據存放在同一文(wén)件中(zhōng)跨平台,
可(kě)自由複制。
SQLite 内部構造:
[img]http://dl2.iteye.com/upload/attachment/0104/3780/9215176d-cf77-33f6-9b1c-885ea36d90f1.jpg
SQLite 根本上相符 SQL-92 标準,和(hé)其他的重要 SQL 數據庫沒什麼差别。它的長處就是高效,Android 運行時情況包含了完全的 SQLite。
SQLite 和(hé)其他數據庫最大年夜的不合就是對數據類型的支撐,創建一個(gè)表時,可(kě)以在 CREATE TABLE 語句中(zhōng)指定某列的數據類型,然則你(nǐ)可(kě)以把任何數據類型放入任何列中(zhōng)。當某個(gè)值插入數據庫時,SQLite 将檢查它的類型。如(rú)不雅該類型與接洽關(guān)系的列不匹配,則 SQLite 會測驗測驗将該值轉換成該列的類型。如(rú)不雅不克不及轉換,則該值将作為其本身具有的類型存儲。比如(rú)可(kě)以把一個(gè)字符串(String)放入 INTEGER 列。SQLite 稱這為“弱類型”(manifest typing.)。 此外,SQLite 不支撐一些标準的 SQL 功能,特别是外鍵束縛(FOREIGN KEY constrains),嵌套 transcaction 和(hé) RIGHT OUTER JOIN 和(hé) FULL OUTER JOIN, 還有一些 ALTER TABLE 功能。 除了上述功能外,SQLite 是一個(gè)完全的 SQL 體系,擁有完全的觸發器(qì),交易等等。
Android 集成了 SQLite 數據庫 Android 在運行時(run-time)集成了 SQLite,所以每個(gè) Android 應用法度榜樣都可(kě)以應用 SQLite 數據庫。
對于熟悉 SQL 的開辟人員來時,在 Android 開辟中(zhōng)應用 SQLite 相當簡單。然則,因為 JDBC 會消費太多的體系資(zī)本,所以 JDBC 對于手機這種内存受限設備來說并不合适。是以,Android 供給了一些新的 API 來應用 SQLite 數據庫,Android 開辟中(zhōng),法度榜樣員須要學應用這些 API。
數據庫存儲在 data/< 項目文(wén)件夾 >/databases/ 下(xià)。 Android 開辟中(zhōng)應用 SQLite 數據庫 Activites 可(kě)以經由過程 Content Provider 或者 Service 拜訪一個(gè)數據庫。
下(xià)面會具體講解如(rú)不雅創建數據庫,添加數據和(hé)萌芽數據庫。 創建數據庫 Android 不主動(dòng)供給數據庫。在 Android 應用法度榜樣中(zhōng)應用 SQLite,必須本身創建數據庫,然後創建表、索引,填充數據。
Android 供給了 SQLiteOpenHelper 贊助你(nǐ)創建一個(gè)數據庫,你(nǐ)隻要持續 SQLiteOpenHelper 類,就可(kě)以輕松的創建數據庫。SQLiteOpenHelper 類根據開辟應用法度榜樣的須要,封裝了創建和(hé)更新數據庫應用的邏輯。
SQLiteOpenHelper 的子(zǐ)類,至少(shǎo)須要實現三個(gè)辦法:
1 構造函數,調用父類 SQLiteOpenHelper 的構造函數。這個(gè)辦法須要四個(gè)參數:高低文(wén)情況(例如(rú),一個(gè) Activity),數據庫名字,一個(gè)可(kě)選的遊标工廠(平日是 Null),一個(gè)代表你(nǐ)正在應用的數據庫模型版本的┞符數。
2 onCreate()辦法,它須要一個(gè) SQLiteDatabase 對象作為參數,根據須要對這個(gè)對象填充表和(hé)初始化數據。
3 onUpgrage() 辦法,它須要三個(gè)參數,一個(gè) SQLiteDatabase 對象,一個(gè)舊的版本号和(hé)一個(gè)新的版本号,如(rú)許你(nǐ)就可(kě)以清跋假使何把一個(gè)數據庫大年夜舊的模型改變到新的模型。
下(xià)面示例代碼展示了若何持續 SQLiteOpenHelper 創建數據庫:
Java代碼
- public class DatabaseHelper extends SQLiteOpenHelper {
- DatabaseHelper(Context context, String name, CursorFactory cursorFactory, int version)
- {
- super(context, name, cursorFactory, version);
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- // TODO 創建數據庫後,對數據庫的操作
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO 更改數據庫版本的操作
- }
- @Override
- public void onOpen(SQLiteDatabase db) {
- super.onOpen(db);
- // TODO 每次成功打開數據庫後起首被履行
- }
- }
接下(xià)來評論辯論具體若何創建表、插入數據、删除表等等。調用 getReadableDatabase() 或 getWriteableDatabase() 辦法,你(nǐ)可(kě)以獲得 SQLiteDatabase 實例,具體調用那個(gè)辦法,取決于你(nǐ)是否須要改變數據庫的内容:
Java代碼
- db=(new DatabaseHelper(getContext())).getWritableDatabase();
- return (db == null) ? false : true;
膳绫擎這段代碼會返回一個(gè) SQLiteDatabase 類的實例,應用這個(gè)對象,你(nǐ)就可(kě)以萌芽或者修改數據庫。 當你(nǐ)完成了對數據庫的操作(例如(rú)你(nǐ)的 Activity 已經封閉),須要調用 SQLiteDatabase 的 Close() 辦法來釋放掉落數據庫連接。 創建表和(hé)索引 為了創建表和(hé)索引,須要調用 SQLiteDatabase 的 execSQL() 辦法來履行 DDL 語句。如(rú)不雅沒有異常,這個(gè)辦法沒有返回值。
例如(rú),你(nǐ)可(kě)以履行如(rú)下(xià)代碼:
db.execSQL(“CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, value REAL);”);
這條語句會創建一個(gè)名為 mytable 的表,表有一個(gè)列名為 _id,并且是主鍵,這列的值是會主動(dòng)增長的┞符數(例如(rú),當你(nǐ)插入一行時,SQLite 會給這列主動(dòng)賦值),别的還有兩列:title( 字符 ) 和(hé) value( 浮點數 )。 SQLite 會主動(dòng)為主鍵列創建索引。 平日情況下(xià),第一次創建數據庫時創建了表和(hé)索引。
如(rú)不雅你(nǐ)不須要改變表的 schema,不須要删除表和(hé)索引 . 删除表和(hé)索引,須要應用 execSQL() 辦法調用 DROP INDEX 和(hé) DROP TABLE 語句。 給表添加數據 膳绫擎的代碼,已經創建了數據庫和(hé)表,如(rú)今須要給表添加數據。有兩種辦法可(kě)以給表添加數據。
像膳绫擎創建表一樣,你(nǐ)可(kě)以應用 execSQL() 辦法履行 INSERT, UPDATE, DELETE 等語句來更新表的數據。execSQL() 辦法實用于所有不返回結不雅的 SQL 語句。
例如(rú): db.execSQL(“INSERT INTO widgets (name, inventory)”+ “VALUES (‘Sprocket’, 5)”);
另一種辦法是應用 SQLiteDatabase 對象的 insert(), update(), delete() 辦法。這些辦法把 SQL 語句的一部分作為參數。
示例如(rú)下(xià):
Java代碼
- ContentValues cv=new ContentValues();
- cv.put(Constants.TITLE, "example title");
- cv.put(Constants.VALUE, SensorManager.GRAVITY_DEATH_STAR_I);
- db.insert("mytable", getNullColumnHack(), cv);
update()辦法有四個(gè)參數,分别是表名,表示列名和(hé)值的 ContentValues 對象,可(kě)選的 WHERE 前提和(hé)可(kě)選的填充 WHERE 語句的字符串,這些字符串會調換 WHERE 前提中(zhōng)的“?”标記。
update() 根據前提,更新指定列的值,所以用 execSQL() 辦法可(kě)以達到同樣的目标。 WHERE 前提和(hé)其參數和(hé)用過的其他 SQL APIs 類似。
例如(rú):
String[] parms=new String[] {“this is a string”};
db.update(“widgets”, WordStrments, “name=?”, parms);
delete() 辦法的應用和(hé) update() 類似,應用表名,可(kě)選的 WHERE 前提和(hé)響應的填充 WHERE 前提的字符串。 萌芽數據庫 類似 INSERT, UPDATE, DELETE,有兩種辦法應用 SELECT 大年夜 SQLite 數據庫檢索數據。
1 .應用 rawQuery() 直接調用 SELECT 語句; 應用 query() 辦法構建一個(gè)萌芽。
Raw Queries 正如(rú) API 名字,rawQuery() 是最簡單的解決辦法。經由過程這個(gè)辦法你(nǐ)就可(kě)聲調用 SQL SELECT 語句。
例如(rú): Cursor c=db.rawQuery( “SELECT name FROM sqlite_master WHERE type=’table’ AND name=’mytable’”, null);
在膳绫擎例子(zǐ)中(zhōng),我們萌芽 SQLite 體系表(sqlite_master)檢查 table 表是否存在。返回值是一個(gè) cursor 對象,這個(gè)對象的辦法可(kě)以疊代萌芽結不雅。 如(rú)不雅萌芽是動(dòng)态的,應用這個(gè)辦法就會異常複雜。
例如(rú),當你(nǐ)須要萌芽的列在法度榜樣編譯的時刻不克不及肯定,這時刻應用 query() 辦法會便利很多。
Regular Queries query() 辦法用 SELECT 語句段構建萌芽。SELECT 語句内容作為 query() 辦法的參數,比如(rú):要萌芽的表名,要獲取的字段名,WHERE 前提,包含可(kě)選的地位參數,去替代 WHERE 前提中(zhōng)地位參數的值,GROUP BY 前提,HAVING 前提。 除了表名,其他參數可(kě)所以 null。所以,以前的代碼段可(kě)以可(kě)寫成:
String[] columns={“ID”, ”inventory”};
Java代碼
- String[] parms={"snicklefritz"};
- Cursor result=db.query("widgets", columns, "name=?",parms, null, null, null);
應用遊标
不管你(nǐ)若何履行萌芽,都邑返回一個(gè) Cursor,這是 Android 的 SQLite 數據庫遊标,
應用遊标,你(nǐ)可(kě)以:
經由過程應用 getCount() 辦法獲得結不雅集中(zhōng)有若幹記錄;
經由過程 moveToFirst(), moveToNext(), 和(hé) isAfterLast() 辦法遍曆所有記錄;
經由過程 getColumnNames() 獲得字段名;
經由過程 getColumnIndex() 轉換成字段号;
經由過程 getString(),getInt() 等辦法獲得給定字段當前記錄的值;
經由過程 requery() 辦法從新履行萌芽獲得遊标;
經由過程 close() 辦法釋放遊标資(zī)本;
例如(rú),下(xià)面代碼遍曆 mytable 表:
Java代碼
- Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");
- result.moveToFirst();
- while (!result.isAfterLast()) {
- int id=result.getInt(0);
- String name=result.getString(1);
- int inventory=result.getInt(2);
- // do something useful with these
- result.moveToNext();
- }
- result.close();
在 Android 中(zhōng)應用 SQLite 數據庫治理對象 在其他數據庫上作開辟,一般都應用對象來檢查和(hé)處理數據庫的内容,而不是僅僅應用數據庫的 API。
應用 Android 模仿器(qì),有兩種可(kě)供選擇的辦法來治理數據庫。
起首,模仿器(qì)綁定了 sqlite3 控制台法度榜樣,可(kě)以應用 adb shell 敕令來調用他。隻要你(nǐ)進入了模仿器(qì)的 shell,在數據庫的路(lù)徑履行 sqlite3 敕令就可(kě)以了。
數據庫文(wén)件一般存放在: /data/data/your.app.package/databases/your-db-name 如(rú)不雅你(nǐ)愛好應用更友愛的對象,你(nǐ)可(kě)以把數據庫拷貝到你(nǐ)的開辟機上,應用 SQLite-aware 客戶妒攀來操作它。如(rú)許的話,你(nǐ)在一個(gè)數據庫的拷貝上操作,如(rú)不雅你(nǐ)想要你(nǐ)的修改能反竽暌鈎到設備上,你(nǐ)須要把數據庫備份歸去。
把數據庫大年夜設備上考出來,你(nǐ)可(kě)以應用 adb pull 敕令(或者在 IDE 上做響應操作)。
存儲一個(gè)修悛改的數據庫到設備上,應用 adb push 敕令。 一個(gè)最便利的 SQLite 客戶端是 FireFox SQLite Manager 擴大,它可(kě)以跨所有平台應用。
下(xià)圖是SQLite Manager對象:
[img]http://dl2.iteye.com/upload/attachment/0104/3785/e6fabbe0-0372-34ff-b96b-8ddbfc322f89.jpg
如(rú)不雅你(nǐ)想要開辟 Android 應用法度榜樣,必定須要在 Android 上存儲數據,應用 SQLite 數據庫是一種異常好的選擇。
第五種: 收集存儲數據
前面介紹的幾種存儲都是将數據存儲在本地設備上,除此之外,還有一種存儲(獲取)數據的方法,經由過程收集來實現數據的存儲和(hé)獲取。
我們可(kě)聲調用WebService返回的數據或是解析HTTP協定實現收集數據交互。
具體須要熟悉java.net.*,Android.net.*這兩個(gè)包的内容,在這就不贅述了,請大年夜家參閱相幹文(wén)檔。
下(xià)面是一個(gè)經由過程地區名稱萌芽該地區的氣象預告,以POST發送的方法發送請求到webservicex.net站(zhàn)點,拜訪WebService.webservicex.net站(zhàn)點上供給萌芽氣象預告的辦事。
代碼如(rú)下(xià):
Java代碼
- package com.android.weather;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.http.HttpResponse;
- import org.apache.http.NameValuePair;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.protocol.HTTP;
- import org.apache.http.util.EntityUtils;
- import android.app.Activity;
- import android.os.Bundle;
- public class MyAndroidWeatherActivity extends Activity {
- //定義須要獲取的内容來源地址
- private static final String SERVER_URL =
- "http://www.webservicex.net/WeatherForecast.asmx/GetWeatherByPlaceName";
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- HttpPost request = new HttpPost(SERVER_URL); //根據内容來源地址創建一個(gè)Http請求
- // 添加一個(gè)變量
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- // 設置一個(gè)地區名稱
- params.add(new BasicNameValuePair("PlaceName", "NewYork")); //添加必須的參數
- try {
- //設置參數的編碼
- request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
- //發送請求并獲取反饋
- HttpResponse httpResponse = new DefaultHttpClient().execute(request);
- // 解析返回的内容
- if(httpResponse.getStatusLine().getStatusCode() != 404){
- String result = EntityUtils.toString(httpResponse.getEntity());
- System.out.println(result);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
别忘記了在設備文(wén)件中(zhōng)設置拜訪收集權限:
Java代碼
- <uses-permission android:name="android.permission.INTERNET" />