第6章 数据存储全方案,详解持久化技术
所有的App都可以說是與數據打交道的,離開數據它們什么都不是.那么平時我們怎么存儲一些關鍵的數據呢?
1 持久化技術簡介
數據持久化就是指將那些內存中的瞬時數據保存到存儲設備中,保證即使在手機或電腦關機的情況下,這些數據仍然不會丟失。保存在內存中的數據是處于瞬時狀態的,而保存在存儲設備中的數據是處于持久狀態的,持久化技術則是提供了一種機制可以讓數據在瞬時狀態和持久狀態之間進行轉換。
Android系統中主要提供了三種方式用于簡單地實現數據持久化功能,即文件存儲、SharedPreference存儲以及數據庫存儲。當然,除了這三種方式之外,你還可以將數據保存在手機的SD卡中,不過使用文件、SharedPreference或數據庫來保存數據會相對更簡單一些,而且比起將數據保存在SD卡中會更加的安全。
2 文件存儲
????文件存儲是Android中最基本的一種數據存儲方式,它不對存儲的內容進行任何的格式化處理,所有數據都是原封不動地保存到文件當中的,因而它比較適合用于存儲一些簡單的文本數據或二進制數據.
2.1 將數據存儲到文件中
Context類中提供了一個openFileOutput ()方法,可以用于將數據存儲到指定的文件中。
openFileOutput ()方法返回的是一個FileOutputStream對象,得到了這個對象之后就可以使用Java流的方式將數據寫入到文件中了.
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(openFileOutput("data", Context.MODE_PRIVATE)));
writer.write(data);
?
那么我們來創建一個實際的例子,使用openFileOutput()來進行數據存儲.
S1:在activity_main.xml中創建一個EditText控件
S2:在MainActivity.java中運用openFileOutput()方法保存數據
S3:運行項目并查看
?
2.2 從文件中讀取數據
????將數據存儲到文件中,Context類中還提供了一個openFileInput()方法,用于從文件中讀取數據.
????例子程序:
????
3 SharedPreferences存儲
不同于文件儲存方式,SharedPreferences采用鍵值對的方式進行存儲.也就是說,但保存或獲取一個數據,必須同時提供這個數據的Key值.
并且,SharedPreferences可以保存不同類類型的數據,如果保存的是整數,那么取出的就是整數;如果保存的是String字符串,那么取出的也是字符串.
具體的用法下面會詳述.
3.1 將數據存儲到SharedPreferences中
要使用SharedPreferences保存數據就必須在程序中獲得SharedPreferences.這個對象有三種方式獲取:
1)Context類中的的getSharedPreferences()方法:這個參數會傳入兩個參數,SharedPreferences的文件名和操作模式.如果傳入的文件名不存在,則會在/data/data/<packagename>/shared_prefs/目錄下;操作模式有兩種,MODE_PRIVATE和MODE_MULTI_PROCESS.MODE_PRIVATE指的是只有當前程序才能對該文件進行讀取,MODE_MULTI_PROCESS一般用于多個進程對這個文件進行訪問.(MULTI 許多)
2)Activity類中的getPreferences()方法:與上面這個方法比,這個方法只接受一個參數,就是操作模式的參數.文件名默認為當前活動的類名.
3)PreferenceManager類中的getDefaultSharedPreferences()方法:這是一個靜態方法,它接受一個Context參數.并默認使用當前活動的包名作為前綴來命名SharedPreferences文件
?
得到SharedPreferences對象后,就可以向SharedPreferences文件進行數據存儲了.存儲的步驟分為三步:
S1:調用SharedPreferences對象的edit()方法來獲取一個SharedPrefences.Editor對象
S2:用SharedPrefences.Editor對象的putXxx()方法,向Editor對象中添加數據
S3:調用commit()方法,提交并存儲數據
?
例子程序:
activity_main.xml
MainActivity.java
?
我們看看實際效果:
實際上他是以XML文件進行存儲的
3.2 從SharedPreferences中讀取數據
直接上代碼說明使用方法:
S1:在activity_main.xml文件中新建一個Button
S2:在MainActivity.java中書寫這個Button的點擊事件
3.3 實現記住密碼功能
S1:實現一個lauout:Login.xml
????
S2:創建LoginActivity.java
S3:在AndroidMainfest.xml中注冊Login.xml和activity_main.xml文件
S4:運行程序
4 SQLite數據庫存儲
Android OS中行有個DB---SQLite數據庫.Android中的SQLite數據庫到底是如何使用的呢?
4.1 創建數據庫
Android為了讓我們能夠更加方便地管理數據庫,專門提供了一個SQLiteOpenHelper幫助類,借助這個類就可以非常簡單地對數據庫進行創建和升級;
1) SQLiteOpenHelper是一個抽象類.如果我們想要使用它的話,就需要創建一個自己的幫助類去繼承它。
2) SQLiteOpenHelper中有兩個抽象方法,分別是onCreate()和onUpgrade(),我們必須在自己的幫助類里面重寫這兩個方法,然后分別在這兩個方法中去實現創建、升級數據庫的邏輯.
3) SQLiteOpenHelper中還有兩個非常重要的實例方法,getReadableDatabase()和getWritableDatabase()。這兩個方法都可以創建或打開一個現有的數據庫(如果數據庫已存在則直接打開,否則創建一個新的數據庫),并返回一個可對數據庫進行讀寫操作的對象
4) SQLiteOpenHelper中有兩個構造方法可供重寫,一般使用參數少一點的那個構造方法即可。這個構造方法中接收四個參數,第一個參數是Context,這個沒什么好說的,必須要有它才能對數據庫進行操作。第二個參數是數據庫名,創建數據庫時使用的就是這里指定的名稱。第三個參數允許我們在查詢數據的時候返回一個自定義的Cursor,一般都是傳入null。第四個參數表示當前數據庫的版本號,可用于對數據庫進行升級操作。構建出SQLiteOpenHelper的實例之后,再調用它的getReadableDatabase()或getWritableDatabase()方法就能夠創建數據庫了,數據庫文件會存放在/data/data/<package name>/databases/目錄下。此時,重寫的onCreate()方法也會得到執行,所以通常會在這里去處理一些創建表的邏輯。
?
實例:
S1:創建繼承SQLiteOpenHelper的實現類MyDatabaseHelper,并重寫onCreate()方法
S2:在MainActivity.java中調用getWritableDatabase()方法
驗證下數據庫是否生成:
4.2 升級數據庫
考慮一個情況,現在我們的數據庫中已經有一張記錄各個書的詳細信息表Book,現在我們需要添加一張用戶記錄書籍分類的表Category,那么該怎么做呢?
創建Category表的語句為:
create table Category (
id integer primary key autoincrement,
category_name text,
category_code integer)
這個需求是不是直接在MyDatabaseHelper.java中加入上述Create語句,并在onCreate()方法中調用呢?
當然不是!
???? 其實沒有創建成功的原因不難思考,因為此時BookStore.db數據庫已經存在了,之后不管我們怎樣點擊Create database按鈕,MyDatabaseHelper中的onCreate()方法都不會再次執行,因此新添加的表也就無法得到創建了。
???? 解決方案就是在上面的基礎上修改onUpgrade()方法:
????注意,這個時候在MainActivity.java中,調用MyDatabaseHelper的構造方法時輸入的第四個參數要有所不同:
????
?
4.3 添加數據
見面介紹的是創建和升級數據庫,下面的部分我們著重介紹對數據庫的CRUD操作(C的操作前面已經介紹)
考慮到開發者的水平總是參差不齊(是否能夠熟練的使用SQL語句),Android OS提供了一些列輔助方法-----在Android中即使不使用SQL語句,也能輕松的完成CRUD操作.
我們曉得的是,嗲用SQLiteOpenHelper的getReadableDatabase()或者getWritableDatabase()方法是可以創建/升級數據庫的,且這兩個方法還會返回一個SQLiteDatabase對象,借助這個對象我們可以對數據進行CRUD操作,具體看Android的API文檔.
添加操作主要使用SQLiteDatabase的insert()方法,這個方法就是專門用于添加數據的。它接收三個參數,第一個參數是表名,我們希望向哪張表里添加數據,這里就傳入該表的名字。第二個參數用于在未指定添加數據的情況下給某些可為空的列自動賦值NULL,一般我們用不到這個功能,直接傳入null即可。第三個參數是一個ContentValues對象,它提供了一系列的put()方法重載,用于向ContentValues中添加數據,只需要將表中的每個列名以及相應的待添加數據傳入即可.
例子程序:
S1:在布局文件中添加一個按鈕
S2:修改MainActivity中的代碼
最后的結果為:
?
4.4 更新數據
????SQLiteDatabase中也是提供了一個非常好用的update()方法用于對數據進行更新,這個方法接收四個參數,第一個參數和insert()方法一樣,也是表名,在這里指定去更新哪張表里的數據。第二個參數是ContentValues對象,要把更新數據在這里組裝進去。第三、第四個參數用于去約束更新某一行或某幾行中的數據,不指定的話默認就是更新所有行。
例子程序:
S1:在布局文件中添加一個按鈕
S2:修改MainActivity中的代碼
最后的結果:
4.5 刪除數據
????SQLiteDatabase中提供了一個delete()方法專門用于刪除數據,這個方法接收三個參數,第一個參數仍然是表名,這個已經沒什么好說的了,第二、第三個參數又是用于去約束刪除某一行或某幾行的數據,不指定的話默認就是刪除所有行
例子程序:
S1:在布局文件中添加一個按鈕
S2:修改MainActivity中的代碼
結果:
4.6 查詢數據
數據查詢也是CRUD操作中最難的一部分.(科普下,SQL的全稱是Structured Query Language,結構化查詢語言,所以它的大部分功能體現在"查"上)本小節只會介紹Android的查詢.
SQLiteDatabase有一個query()的方法進行數據查詢.這個方法十分復雜,它有4個重載方法:
我們這里介紹個參數最少的方法,它有7個參數!
這里我們寫一個最簡單的例子,其他的看Android 的 API去.
?
4.7 使用SQL操作數據庫
????Android 的SQLite數據庫也可以直接使用SQL語言進行操作上述所有過程
方法如下:
添加數據的方法如下:
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
更新數據的方法如下:
db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code" });
刪除數據的方法如下:
db.execSQL("delete from Book where pages > ?", new String[] { "500" });
查詢數據的方法如下:
db.rawQuery("select * from Book", null);
5 SQLite數據庫的最佳實踐
這里我們簡單的介紹SQLite數據的兩個進階技巧
5.1 使用事務
數據庫是有事務的概念的,那么在Android的SQLite中如何實現事務呢?
比如,現在Book表里面的數據已經很老了,我們需要全部刪除后添加一些新的數據.這個操作我們需要在一個事務中完成,如何操作呢?
S1:添加一個按鈕,用于觸發替換數據操作,id定義為replace_data
S2:在這個按鈕的觸發事件中加入事務
5.2 升級數據庫的最佳寫法
????回憶下我們前面的升級數據庫的操作,其實特別的不妥----我們為了保證數據庫是最新的,我們只是在onUpgrade()方法中刪除掉所有的表,然后再重新執行下onCreate()方法----這種方法實在不妥,每次的升級會刪除前面所有操作的表中的數據,這對應用程序是不允許的.
回憶下我們創建數據庫對象DataHelper時,傳入的參數中最后一個代表數據庫版本.我們可以這么做,比較傳入的版本號與現有數據庫的的版本號的差異,然后分別執行"差異的部分",做相應的改變.
?
A) 第一版程序:只需創建一張Book表,那么MyDatabaseHelper的代碼如下:
?
B)幾周后,我們有了新的需求:需要向數據庫中添加一張Category表,于是我們這么修改代碼:
這樣修改代碼的好處是,當用戶直接安裝版本二的時候會執行onCreate()方法創建數據庫;當用戶由版本一升級到版本二時,只會創建Category表,原來的Book表不會產生任何變化.
?
C)沒過多久,新的需求又來了!這次需要個Book表和Category表建立關聯(在Book表中新增一個category_id的字段),代碼修改如下:
?
但是!請特別注意,B和C的代碼有個嚴重的錯誤(細節)需要注意.先拋出結論,在onUpgrade()方法里,switch中每一個case后面建議不要加break關鍵字.
這是為什么呢?
如果用戶由版本一直接升級到版本三,那么實際(如果加break關鍵字)DB只會升級到版本二!
6 小結與點評
本章主要是對Android常用的數據持久化方式進行了詳細的講解,包括文件存儲、SharedPreferences存儲以及數據庫存儲。其中文件適用于存儲一些簡單的文本數據或者二進制數據,SharedPreferences適用于存儲一些鍵值對,而數據庫則適用于存儲那些復雜的關系型數據。
轉載于:https://www.cnblogs.com/angel-of-death/p/5575695.html
總結
以上是生活随笔為你收集整理的第6章 数据存储全方案,详解持久化技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS开发学习之MapKit - 获得在
- 下一篇: Postgre约束详解