一個好的開發(fā)平臺要對數(shù)據(jù)的存儲有良好的支持矗漾,而不是僅靠保存在內(nèi)存中的瞬時數(shù)據(jù)颜武。本篇主要介紹Android平臺實現(xiàn)數(shù)據(jù)存儲的三種方式令宿,分別是:
- File 文件存儲
- SharedPreferences存儲
- SQLite數(shù)據(jù)庫存儲
在分別介紹之前寇荧,先要知道以上三種方法使得數(shù)據(jù)文件都默認(rèn)存儲在哪里刽脖,方便后續(xù)驗證悼粮,如圖:
另外,關(guān)于如何在DDMS里File Explore下打開data文件夾以及導(dǎo)出文件在技能篇有詳細(xì)說明曾棕,本篇不再贅述扣猫,驗證時將直接展示導(dǎo)出文件內(nèi)容。
1.File文件存儲
在Android中寫入和讀取文件的方法翘地,和 Java中實現(xiàn)I/O的程序是一樣的申尤,Context類中提供了openFileInput()和openFileOutput()方法來打開數(shù)據(jù)文件里的文件IO流癌幕。下面直接通過一個demo學(xué)習(xí)Android如何通過文件來保存數(shù)據(jù)。
(1)寫入數(shù)據(jù)
新建布局mylayout.xml昧穿,只加入一個EditText用于輸入文本內(nèi)容:
新建MyActivity勺远,在onCreate()獲取EditText實例,然后重寫onDestory()為了在活動銷毀之前將輸入的文本內(nèi)容存儲起來时鸵。具體方法是:先獲取了EditText中輸入的文本text胶逢,然后openFileOutput()方法將text存儲到名為data的文件中并且能夠得到一個FileOutputStream 對象,饰潜,再借助它構(gòu)建出一 個OutputStreamWriter對象初坠,接著再使用OutputStreamWriter 構(gòu)建出一個 BufferedWriter 對象,這樣就可以通過BufferedWriter來將文本內(nèi)容寫入到文件中了彭雾。
關(guān)鍵方法:
FileOutputStream fileOutputStream = openFileOutput("data", Context.MODE_PRIVATE);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
bufferedWriter.write(text);
其中openFileOutput()的第二個參數(shù)碟刺,表示文件的操作模式,常用的可選值含義見下圖:
運(yùn)行程序薯酝,在輸入框里輸入Hello AS半沽!然后退出程序。
查看DDMS吴菠,果然有data文件者填!導(dǎo)出后內(nèi)容和輸入完全一致,證實了內(nèi)容確實成功保存到文件了做葵。
(2)讀取數(shù)據(jù)
接下來我們想讓程序再次啟動時輸入框內(nèi)已經(jīng)顯示剛剛寫入的數(shù)據(jù)占哟。在OnCreate()中用openFileInput()方法指定了要從文件data中讀取數(shù)據(jù),之后代碼和寫入是對應(yīng)的非常好理解蜂挪。讀取到內(nèi)容之后判斷是否為空重挑,若不為空嗓化,就set到EditText里棠涮,并調(diào)用setSelection 方法將輸入光標(biāo)移動到文本的末尾位置以便于繼續(xù)輸入,再彈出一句重新加載成功的提示刺覆。
關(guān)鍵方法:
FileInputStream fileInputStream=openFileInput("data");
bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String line;
while((line=bufferedReader.readLine())!=null){
content.append(line);
}
運(yùn)行程序严肪,效果如圖:
2.SharePreferences存儲
SharePreferences是一種輕型的數(shù)據(jù)存儲方式,常用來存儲一些簡單的配置信息谦屑,如int驳糯、string、boolean氢橙、float和long酝枢。它的本質(zhì)是基于XML文件存儲key-value鍵值對數(shù)據(jù)。
實現(xiàn)SharedPreferences存儲的步驟如下:
(1)調(diào)用getSharedPreferences()方法獲得SharedPreferences對象悍手,提供兩個參數(shù)帘睦,指定文件名和操作模式袍患。
(2)調(diào)用SharedPreference對象的edit()方法獲得SharedPreferences.Editor引用對象
(3)調(diào)用Edit接口的形如put某某某()方法以鍵值對形式保存某某某類型的數(shù)據(jù)
(4)調(diào)用Edit接口的commit()方法提交鍵值對。
一定注意竣付,不用SharedPreferences對象去存儲或修改數(shù)據(jù)诡延,而是通過Editor對象。但獲取數(shù)據(jù)時需要調(diào)用SharedPreferences對象的get某某某()方法了古胆。
學(xué)習(xí)完SharePreferences基本知識點后肆良,通過一個有記住密碼功能的demo來鞏固一下吧!新建login.xml逸绎,這里做一個登陸界面惹恃,如下圖所示。相信這樣的一個頁面難不倒你桶良,布局嵌套就能實現(xiàn)了座舍。
在MainActvity的onCreate()里先獲取除了TextView的所有控件眠蚂、實例化SharedPreferences和SharedPreferences.Editor晰洒、給兩個按鈕都注冊擊事件掀虎,代碼如下:
再來看看點擊事件跟伏,當(dāng)點擊cancel時荚斯,直接finish()結(jié)束當(dāng)前活動指厌;當(dāng)點擊login時淋淀,第一輪判斷用戶名和密碼是否對應(yīng)(假設(shè)只有一個賬戶)震鹉,如果不對應(yīng)就彈出提示登陸不成功纲爸,如果對應(yīng)就提示登陸成功并跳轉(zhuǎn)到另一個頁面亥鸠,在跳轉(zhuǎn)之前要進(jìn)行第二輪判斷以保證數(shù)據(jù)不丟失,判斷CheckBox是否選中识啦,如果未選中就用Edit清除所有數(shù)據(jù)负蚊,如果選中就添加用戶名和密碼,注意最后一定要commit提交颓哮。
下兩個圖就是跳轉(zhuǎn)頁面的布局和活動了家妆。
最后再回到MainActivity的onCreate()方法中,下面這段代碼的含義是:當(dāng)用戶選中復(fù)選框并且成功登陸一次之后冕茅,那么MyPres文件里肯定有數(shù)據(jù)了伤极,這時如果重啟登陸界面,SharedPreferences就會獲取文件中數(shù)據(jù)并且呈現(xiàn)在輸入框里了姨伤;當(dāng)沒有數(shù)據(jù)說明第一次打開界面或者用戶不需要記住密碼功能就什么也不需要顯示了哨坪。
運(yùn)行程序,測試一下:
并且記住密碼功能也能很好的實現(xiàn)乍楚,這里就不展示了当编。如果用戶選中復(fù)選框那么MyPres文件里就有數(shù)據(jù)了,見下圖:
3.SQLite數(shù)據(jù)庫存儲
SQLite是一款輕量級的關(guān)系型數(shù)據(jù)庫徒溪,它的運(yùn)算速度非撤尥担快拧篮,占用資源很少,在存儲大量復(fù)雜的關(guān)系型數(shù)據(jù)的時可以使用牵舱,比前面學(xué)過的只適用于存儲簡單數(shù)據(jù)的兩種存儲方式要好很多串绩。接下來學(xué)習(xí)如何創(chuàng)建、升級數(shù)據(jù)庫以及對數(shù)據(jù)進(jìn)行增刪改查芜壁,并穿插一個完整的例子更好的掌握這些知識點礁凡。
(1)創(chuàng)建數(shù)據(jù)庫
先學(xué)習(xí)一個類SQLiteOpenHelper,它是SQLiteDatabase的幫助類慧妄, 用于管理數(shù)據(jù)庫的創(chuàng)建和升級顷牌。SQLiteOpenHelper的使用步驟:
第一步:自定義幫助類并繼承SQLiteOpenHelper,并重寫兩個方法:onCreate()和 onUpgrade()塞淹,分別在這兩個方法中去實現(xiàn)創(chuàng)建窟蓝、升級數(shù)據(jù)庫的邏輯。還需要一個構(gòu)造方法饱普,這里用含有四個參數(shù)的構(gòu)造方法就可以运挫,如圖:
第二步:創(chuàng)建數(shù)據(jù)庫時,先實例化一個自定義的幫助類套耕,并提供四個參數(shù)谁帕,含義是(上下文,數(shù)據(jù)庫名冯袍,創(chuàng)建Cursor的工廠類匈挖,版本號)。
第三步:用幫助類對象的getReadableDatabase() 和getWritableDatabase()去創(chuàng)建或打開一個現(xiàn)有的數(shù)據(jù)庫(如果數(shù)據(jù)庫已存在則直接打開康愤,否則創(chuàng)建一個新的數(shù)據(jù)庫)儡循,并返回一個可對數(shù)據(jù)庫SQLiteDatabase。
第四步:之后就可以利用得到的數(shù)據(jù)庫進(jìn)行增刪改查的操作了征冷。
下面就來做個demo吧择膝!從自定義幫助類開始,并重寫兩個方法及構(gòu)造函數(shù)资盅。在這里用幫助類幫助創(chuàng)建一個student表调榄,包含學(xué)生的學(xué)號踊赠、姓名呵扛、年齡和年級,對應(yīng)的SQL語句就放在一個字符串常量里筐带。特別要注意語句一定要準(zhǔn)確今穿,多個空格都會建表失敗。在onCreate()方法里會返回一個SQLiteDatabase對象伦籍,接下來終于接觸到SQLiteDatabase的第一個常用方法execSQL()蓝晒,這個方法非常萬能腮出,它可接受和處理SQL語句,換句話說芝薇,后面將要學(xué)習(xí)的增刪改查不僅可以用提供好的現(xiàn)成的輔助性方法胚嘲,還可直接用原生SQL語句再調(diào)用execSQL()就夠了,在后面的學(xué)習(xí)中只介紹前一種方法洛二。這里就調(diào)用execSQL()去創(chuàng)建表并打印一行提示的Toast馋劈。一個自定義幫助類構(gòu)建好了!
然后新建布局晾嘶,并放入五個按鈕妓雾,對應(yīng)創(chuàng)建和增刪改查:
在主活動里獲取所有按鈕實例并注冊點擊事件,在onCreate()實例化幫助類MyHelper垒迂,指定數(shù)據(jù)庫名為student.db械姻,版本號為1。ContentValues類先跳過机断。
接下來實現(xiàn)點擊創(chuàng)建按鈕的效果:調(diào)用getReadableDatabase()創(chuàng)建數(shù)據(jù)庫楷拳,且MyHelper的onCreate()也會執(zhí)行,那么student表也被建立了吏奸。
運(yùn)行程序唯竹,點擊創(chuàng)建有Toast提示!但這不代表student表建立成功苦丁。所以到DDMS下找文件浸颓,確實有student.db數(shù)據(jù)庫,但想要查看它需要別的工具旺拉,所以換一種查看方式产上,用adb shell來檢查,命令如下:
可以證實student表成功建立了蛾狗!
(2)增加數(shù)據(jù)
現(xiàn)在學(xué)習(xí)之前看到的ContentValues類晋涣,常用它put()方法以鍵值對的形式存儲基本類型數(shù)據(jù)。在增和改會用到它沉桌,可以理解為鍵就是表中屬性名谢鹊,值就是表中數(shù)據(jù)。還常用方法clear()清空所有數(shù)據(jù)留凭。
再來學(xué)習(xí)SQLiteDatabase用于增添數(shù)據(jù)的輔助性方法insert()佃扼,三個參數(shù)含義(被操作的表名,空值字段的名稱蔼夜,數(shù)據(jù)即ContentValues對象)兼耀,第二個參數(shù)一般傳入null。學(xué)會之后給student表插入兩行記錄吧,因為id這個屬性設(shè)置了自增長所以可以不用管它:
運(yùn)行程序瘤运,數(shù)據(jù)確實插入成功窍霞!
(3)刪除數(shù)據(jù)
刪除數(shù)據(jù)的輔助性方法是delete(),第一個參數(shù)還是表示表名拯坟,第二第三個參數(shù)用于約束刪除某一行或幾行的數(shù)據(jù)但金。比如需要刪除student表中年齡大于17的記錄:
運(yùn)行,發(fā)現(xiàn)表中第二條記錄果然被刪除了郁季!
(4)更改數(shù)據(jù)
update() 方法提供四個參數(shù)傲绣,(表名,ContentValues對象巩踏,約束秃诵,約束),之前都學(xué)過了塞琼!來試試給表里唯一的學(xué)生Lucy的年級更改為高三:
更改成功菠净!
(5)查詢數(shù)據(jù)
查詢方法quary()復(fù)雜一些,需要至少七個參數(shù)(table, columns, selection, selectionArgs, groupBy, having, orderBy)彪杉,含義是:(表名毅往,要查詢出的列名,查詢條件子句派近,對應(yīng)于selection語句中占位符的值攀唯,要分組的列名,分組后過濾條件渴丸,排序方式)侯嘀。其實也不用害怕,多數(shù)情況下少數(shù)幾個參數(shù)就能完成查詢操作了谱轨。
還沒完戒幔,這個方法會返回一個Cursor,查詢到的數(shù)據(jù)都會從它取出土童。Cursor常用方法:moveToFirst()將指針移動到結(jié)果集的第一行诗茎;getColumnIndex()獲取某一列在表中對應(yīng)位置的索引;get某某某()傳入索引以獲取相應(yīng)位置的某種類型的數(shù)據(jù)献汗;close()關(guān)閉指針敢订。下面來查詢student表中所有數(shù)據(jù):
打印出的日志結(jié)果如圖:
(6)升級數(shù)據(jù)庫
MyHelper里需要重寫的第二個方法onUpdate()用于幫助數(shù)據(jù)庫進(jìn)行版本更新。比如此刻需要在數(shù)據(jù)庫再添加一張表course罢吃,只要在update()寫好創(chuàng)建course的操作楚午,然后想辦法讓它被調(diào)用就好了。還記得在實例化幫助類是需要傳入的第四個參數(shù)版本號嗎刃麸?之前的傳入的是1醒叁,只要傳入一個比1大的數(shù)就可以讓update()執(zhí)行了司浪。在下圖代碼里利用了oldVersion去判斷舊版本號泊业,如果是1就只需要再建course表把沼,如果初次運(yùn)行程序,就只會執(zhí)行onCreate()方法然后兩張表就一起建立了吁伺。這樣做的好處是無論更新到第幾代都不會影響之前的操作數(shù)據(jù)饮睬,也能保證當(dāng)前版本是最新的。
修改版本號為2:
重新運(yùn)行程序篮奄,點擊創(chuàng)建捆愁,student表不會再創(chuàng)建而只會創(chuàng)建course表!
補(bǔ)充閱讀:Litepal是一個輕型的數(shù)據(jù)庫操作框架窟却,采用了對象關(guān)系映射的模式昼丑,并對常用的數(shù)據(jù)庫操作進(jìn)行了封裝,使用它會方便很多夸赫。感興趣可見:項目主頁菩帝,使用方法.
數(shù)據(jù)持久化技術(shù)就學(xué)習(xí)到這里~
> 下一篇預(yù)告:組件篇之ContentProvider