? ? ? ? ?任何一個應(yīng)用程序浪南,其實(shí)說白了就是在不停地和數(shù)據(jù)打交道笼才,我們聊QQ、看新聞络凿、刷微博骡送,所關(guān)心的都是里面的數(shù)據(jù),沒有數(shù)據(jù)的應(yīng)用程序就變成了一個空殼子絮记,對用戶來說沒有任何實(shí)際用途摔踱。呢么這些數(shù)據(jù)都是從哪里來的啦?現(xiàn)在多數(shù)的數(shù)據(jù)都是由用戶產(chǎn)生的怨愤,比如你發(fā)微博派敷,評論新聞,其實(shí)都是在產(chǎn)生數(shù)據(jù)。
? ? ? ? 而我們前面章節(jié)所編寫的眾多例子中也有用到各種各樣中的數(shù)據(jù)篮愉,例如3章最佳時間部分在登錄界面輸入賬號和密碼腐芍。這些數(shù)據(jù)都有一個共同點(diǎn),及他們都是屬于瞬間數(shù)據(jù)试躏。那么什么是瞬間數(shù)據(jù)啦猪勇?就是指那么數(shù)據(jù)存儲在內(nèi)存當(dāng)中,有可能會因?yàn)槌绦蜿P(guān)閉或其他原因?qū)е聝?nèi)存被回收而丟失的數(shù)據(jù)颠蕴。這對于一些關(guān)鍵性數(shù)據(jù)是絕對不能容忍的泣刹,誰都不希望自己剛發(fā)出去的微博,刷新一下就沒了吧犀被!那么怎樣才能保證一些關(guān)鍵性數(shù)據(jù)不會丟失啦椅您?這就需要用到數(shù)據(jù)持久化了。
6.1 ? 持久化技術(shù)簡介
? ? ? ? 數(shù)據(jù)持久化就是指將那些內(nèi)存中的瞬時數(shù)據(jù)保存到存儲設(shè)備中弱判,保證即使在手機(jī)或電腦關(guān)機(jī)的情況下襟沮,這些數(shù)據(jù)仍然不會丟失。保存在內(nèi)存中的數(shù)據(jù)是處于瞬時狀態(tài)的昌腰,而保存在存儲設(shè)備中的數(shù)據(jù)是處于持久狀態(tài)的开伏,持久化技術(shù)則提供了一種機(jī)制可以讓數(shù)據(jù)在瞬時狀態(tài)和持久狀態(tài)之間進(jìn)行轉(zhuǎn)化。
? ? ? ? 持久化技術(shù)被廣泛應(yīng)用于各種程序設(shè)計(jì)的領(lǐng)域當(dāng)中遭商,而這本書重要探討的自然是Android中數(shù)據(jù)持久化技術(shù)固灵。Android系統(tǒng)中主要提供了3種方式用于簡單的實(shí)現(xiàn)數(shù)據(jù)持久化功能,及文件存儲劫流、ShaerdPreference存儲以及數(shù)據(jù)庫存儲巫玻。當(dāng)然,出了這3中方式之外祠汇,你還可以將數(shù)據(jù)庫保存在SD卡中仍秤,不過使用文件、SharedPreference或數(shù)據(jù)庫會相對更簡單一些可很,而且不起將數(shù)據(jù)保存在SD卡中會更加地安全诗力。
? ? ? ? 那么下面我就講對這3中數(shù)據(jù)持久化的方式一一進(jìn)行詳細(xì)的解釋。
6.2 ? ?文件存儲
? ? ? ? 文件存儲是Android中最基本的一種數(shù)據(jù)存儲方式我抠,他不對存儲的內(nèi)容進(jìn)行任何的格式處理苇本,所有的數(shù)據(jù)都是原封不動的保存到文件中,因而他比較適合存儲一些簡單的文本數(shù)據(jù)或二進(jìn)制數(shù)據(jù)菜拓。如果你想使用文件存儲的方式來保存一些較為復(fù)雜的文本數(shù)據(jù)瓣窄,就炫耀定義一套自己的格式規(guī)范,這樣可以方便之后數(shù)據(jù)從文件中重新解析出來纳鼎。
? ? ? ? 那么首先我們就來看一看俺夕,Android中是如何通過文件保存數(shù)據(jù)的裳凸。
6.2.1 ? 將數(shù)據(jù)存儲到文件中
? ? ? ?Context類中提供了一個openFileOutput()方法,可以用于將數(shù)據(jù)存儲到指定文件中啥么。這個方法接收兩個參數(shù)登舞,第一個參數(shù)是文件名,在文件創(chuàng)建的時候使用的就是一個名稱注意這里指定的文件名不可以包含路徑悬荣,因?yàn)樗械奈募际悄J(rèn)存儲到/data/data/<package name>/files/目錄下的。第二個參數(shù)時文件的操作模式疙剑,主要有兩種模式可選氯迂,MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默認(rèn)的操作模式言缤,表示當(dāng)指定同樣文件名的時候嚼蚀,所寫入的內(nèi)容將會覆蓋源文件中的內(nèi)容,而MODE_APPEND則表示如果該文件已經(jīng)存在管挟,就往文件里面追加內(nèi)容轿曙,不存在就創(chuàng)建文件。其實(shí)文件的操作模式本來還有另外兩種:MODE_WORLD_READABLEhe MODE_MODE_WRITEABLE僻孝,這兩種模式表示允許其他的應(yīng)用程序?qū)ξ覀兂绦蛑械奈募M(jìn)行讀寫操作导帝,不過由于這兩種模式過于危險,很容易引起應(yīng)用的安全性漏洞穿铆,已在Android 4.2 版本中被廢棄您单。
openFileOutput()方法返回的是一個FileOutputStream對象,得到了這個獨(dú)享之后就可以使用Java留的方式講述寫入到文件中了荞雏。以下是一段簡單的代碼示例虐秦,展示了如何將一段文本內(nèi)容保存到文件中:
這里只是在布局里面加入了一個EditText,用于輸入文本內(nèi)容凤优。其實(shí)現(xiàn)在你就可以運(yùn)行以下程序了悦陋,界面上肯定會有一個文本輸入框。然后在文本輸入框中隨意輸入點(diǎn)什么內(nèi)容筑辨,再按下Back鍵俺驶,這是輸入的內(nèi)容坑定已經(jīng)丟失了,因?yàn)樗皇撬矔r數(shù)據(jù)挖垛,在活動被銷毀后就會被回收痒钝,而這里我們要做的,就是在數(shù)據(jù)被回收之前痢毒,將它存儲到文件當(dāng)中送矩。修改MainActivity中的代碼,如下所示:
? ? ? ? ? ? 可以看到哪替,首先我們在onCreat()方法中獲取了EditText的實(shí)例栋荸,然后重寫了onDestry()方法,這樣就可以保證在活動銷毀之前一定會調(diào)用這個方法。在onDestry方法中我們獲取了EditText()方法中的代碼和之前的是基本相同晌块,這里就不做解釋了“担現(xiàn)在重新運(yùn)行以下程序,并在EditText中輸入一些內(nèi)容匆背,如圖6.1所示呼伸。
然后按下Back鍵關(guān)閉程序,這時我們輸入的內(nèi)容就已經(jīng)保存到文件中了钝尸。那么如何才能證明使數(shù)據(jù)確實(shí)已經(jīng)成功了啦括享?我們可以借助Android Device Monitor工具來查看一下。點(diǎn)擊as導(dǎo)航欄中的Tools--》Android,會看到如圖6.2所示的工具列表。
點(diǎn)擊android Device Monitor就可以打開Android Device Monitor工具了姜性,然后進(jìn)入File Explorer標(biāo)簽頁,在這里找到/data/data/com.example.filepersistencetest/files/目錄娇斩,可以看到生成了一個data文件,如圖6.3所示:
然后點(diǎn)擊圖6.4中左邊的按鈕可以將這個文件導(dǎo)出到電腦上
使用記事本打開這個文件穴翩,里面的內(nèi)容如圖6.5所示犬第。
這樣就證明了,在Edite中輸入的內(nèi)容確實(shí)應(yīng)景陳宮保存到了文件中了藏否。不過只是成功講述保存下來還不夠瓶殃,我們好需要想辦法在下次啟動程序的時候讓這些數(shù)據(jù)能夠還原到EditText中,因此接下來我們就要學(xué)習(xí)意下如何從文件中讀取數(shù)據(jù)副签。
6.2.2 ?從文件中讀取數(shù)據(jù)
? ? ? ? ? 類似于將數(shù)據(jù)存儲到文件中遥椿,Context類中還提供了一個openFileInput()方法,用于從文件中讀取數(shù)據(jù)淆储。這個方法要比openFileOutput簡單一些冠场,他只接受一個參數(shù),紀(jì)要讀取的文件名本砰,然后系統(tǒng)會自動到data/data/<package name>/files/目錄下去加載這個文件碴裙,并然會一個FileInputStream對象,得到了這個對象之后再通過java流的方式就可以將數(shù)據(jù)讀取出來了点额。
? ? ? ? ?以下是一段簡單的代碼示例舔株,展示了如何從文件中讀取文本數(shù)據(jù):
? ? ? ? ? ? ?在這段代碼中,首先通過openFileInput()方法獲取到了一個FileInputStream對象还棱,然后借助它又構(gòu)建出了InputStreamReader對象载慈,接著在使用InputStreamReader構(gòu)建出一個BufferedReader對象,這樣我們就可以通過Bufferreader進(jìn)行一行行地讀取珍手,把文件中所有的文本內(nèi)容全部讀取出來办铡,并存放在一個StringBuilder對象中辞做,最后將讀取到的內(nèi)容返回就可以了。
了解了從文件中讀取數(shù)據(jù)的方法寡具,那么我們就來繼續(xù)完善上一小節(jié)中的例子秤茅,是的重新啟動程序是EditText中鞥狗保留我們上次輸入的內(nèi)容。修改MainActivity中的代碼童叠,如下所示:
? ? ? ? ? 可以看到框喳,這里的思路非常簡單,在onCreat()方法中調(diào)用load()方法來讀取文件中存儲的文本內(nèi)容拯钻,如果讀到的內(nèi)容不為null帖努,就調(diào)用EditText的setText()方法將內(nèi)容天聰?shù)紼ditText里,并調(diào)用setSelection()方法將輸入光標(biāo)移動到文本的末尾位置以便于繼續(xù)輸入粪般,然后彈出一句還原成功的提示。load()方法中的細(xì)節(jié)我們在前面已經(jīng)講過污桦,這里就不在追溯了亩歹。
? ? ? ? ?注意,上述代碼在對字符串非空判斷的時候使用了TextUtils.isEmpty()方法凡橱,這是一個非常好用的方法小作,他可以一次性進(jìn)行兩種空值判斷。當(dāng)傳入的字符串等于null或者等于空字符串的時候稼钩,這個方法都會返回true顾稀,從而使得我們不需要先單獨(dú)判斷這兩種空值在使用邏輯運(yùn)算符連接起來了。
? ? ? ? ?現(xiàn)在重新運(yùn)行一下程序坝撑,剛才保存的Context字符串肯定會被填充到EditText中静秆,然后編寫一點(diǎn)其他的內(nèi)容,比如在Edite中輸入Hello巡李,接著按下Back鍵退出程序抚笔,再重新啟動程序,這是剛才輸入的內(nèi)容不會丟失侨拦,而是花園道了EditText中殊橙,如圖6.6所示。
? ? ? ? ?這樣我們就已經(jīng)把文件存儲方面的知識學(xué)習(xí)完了狱从,其實(shí)所用到的核心技術(shù)就是Context類中提供的openFileInput()和openFileOutput()方法膨蛮,之后就是利用java的各種流進(jìn)行讀寫操作。
不過正如我前面所說季研,文件存儲的方式并適合用于保存一些較為復(fù)雜的文本數(shù)據(jù)敞葛,因此,下面我么就來學(xué)習(xí)一下Android中另一種數(shù)據(jù)持久化的方式训貌,他比文件存儲更加簡單易用制肮,而且可以很方便的對某一指定的數(shù)據(jù)進(jìn)行讀寫操作冒窍。
6.3 SharePreferences 存儲
? ? ? ? 不同于文件的存儲方式,SharedPreferences是使用鍵值對的方式來存儲數(shù)據(jù)的豺鼻。也就是說综液,當(dāng)保存一條數(shù)據(jù)的時候,需要給這條數(shù)據(jù)提供一個對應(yīng)的鍵儒飒,這樣在讀取數(shù)據(jù)的時候就可以通過這個鍵把相應(yīng)的值取出來谬莹。而且SharedPreferences還支持多種不同的數(shù)據(jù)類型存儲,如果存儲的數(shù)據(jù)類型是整形桩了,那么讀取出來的數(shù)據(jù)也是整形的附帽;如果存儲的數(shù)據(jù)是一個字符串,那么讀取出來的數(shù)據(jù)仍然是字符串井誉。
6.3.1 ? 將數(shù)據(jù)存儲到SharedPreferences 中
? ? ? ? 要想使用SharedPreferences來存儲數(shù)據(jù)蕉扮,首先需要將獲取到SharedPreferences對象。Android中主要提供了3種方法用于得到SharedPreferences對象颗圣。
1.Context類中的getSharedPrefer()方法
? ? ? ? ?此方法接收兩個參數(shù)喳钟,第一個參數(shù)用于指定SharedPreferences文件的名稱,如果指定的文件不存在則會創(chuàng)建一個在岂,SharedPreferences文件都是存在/data/data/<package name>/shared_prefs/目錄下的奔则。第二個參數(shù)用于指定操作模式,目前只有MODE_PRIAVE這一種模式可以選蔽午,它是默認(rèn)的操作模式易茬,和直接傳入0的效果是一樣的,表示只有當(dāng)前應(yīng)用程序才可以對這個SharedPreferences文件進(jìn)行讀寫及老。其他幾種操作模式均已廢棄.
2.Activity類中的getPreference()方法
這個方法和Context中的getSharedPreference()方法很相似抽莱,,不過他只接收一個操作模式參數(shù)写半,因?yàn)槭褂眠@個方法時會自動將當(dāng)前活動的類名作為SharedPreferences的文件名岸蜗。
3.PreferenceManager類中的getDefaultSharedPreferences()方法
這是一個靜態(tài)方法,他接收一個Context參數(shù)叠蝇,并自動使用當(dāng)前應(yīng)用程序的包名作為前綴來命名SharedPreferences文件璃岳。得到了下SharedPreferences對象之后,就可以開始向SharedPreferences文件中存儲數(shù)據(jù)了悔捶,主要可以分為3步實(shí)現(xiàn)铃慷。
(1)調(diào)用SharedPreferences對象的edit()方法來獲取一個SharedPreferences.editor對象。
(2)向SharedPreferences.Editor對象中添加數(shù)據(jù)蜕该,比如添加一個boolean數(shù)據(jù)就是使用putBoolean()方法犁柜,添加一個字符串則使用putString()方法,以此類推堂淡。
(3)調(diào)用apply()方法將添加的數(shù)據(jù)提交馋缅,從而完成數(shù)據(jù)存儲操作扒腕。
不知不覺中已經(jīng)將理論知識介紹的挺多了,那我們就趕快通過一個例子來體驗(yàn)一下SharedPreferences存儲的用法吧萤悴。新建一個SharedPreferencesTest項(xiàng)目瘾腰,然后修改activity_main.xml中的代碼,如下所示:
? ? ? ? ? ? 可以看到覆履,這里首先給按鈕注冊了一個點(diǎn)擊事件蹋盆,然后在點(diǎn)擊事件中通過getShredPreferences()指定文件名為data,并得到了SharedPreferences.Editor對象硝全。接著向這個對象中添加了三條不同類型的數(shù)據(jù)栖雾,最后調(diào)用apply()方法進(jìn)行提交,從而完成了數(shù)據(jù)存儲的操作伟众。
? ? ? ? ? ? 很簡單吧析藕?現(xiàn)在就可以運(yùn)行一下程序了,進(jìn)入程序的主界面后凳厢,點(diǎn)擊一下Save_data按鈕噪径。這時的數(shù)據(jù)應(yīng)該已經(jīng)保存成功了,不過為了證實(shí)一下数初,我們還是要借助File Explorer來進(jìn)行查看。打開Android Device Monitor梗顺,并點(diǎn)擊File Explorer標(biāo)簽頁泡孩,然后進(jìn)入到/data/data/com.comple.sharedpreferencestest/shaared_prefs/目錄下,可以看到生成了一個data.xml文件寺谤,如圖6.7所示仑鸥。
? ? ? ? ? 接下來,同樣十點(diǎn)幾到處按鈕將這個文件到處到電腦上变屁,并用記事本進(jìn)行查看眼俊,里面的內(nèi)容如圖6.8所示。
? ? ? ? ?可以看到粟关,我們剛剛在按鈕的點(diǎn)擊事件中添加的所有數(shù)據(jù)都已經(jīng)成功保存下來了疮胖,并且SharedPreferences文件是使用XML格式來對數(shù)據(jù)進(jìn)行管理的。
? ? ? ? ?那么接下來我們自然要看一看闷板,如何從SharedPreferences文件中讀取這些數(shù)據(jù)了澎灸。
6.3.2 從SharedPreferences 中讀取數(shù)據(jù)
? ? ? ? 你應(yīng)該已經(jīng)感覺到了,使用SharedPreferences來存儲數(shù)據(jù)是非常簡單的不過下面有更好的消息遮晚,其實(shí)從SharedPreferences文件中讀取數(shù)據(jù)會更加的簡單性昭。SharedPreferences對象中提供了一系列的get方法,用于對存儲的數(shù)據(jù)進(jìn)行讀取县遣,每種get方法都對應(yīng)了SharedPreferences.editor中的一種put方法糜颠,比如讀取一個Boolean數(shù)據(jù)就使用getBoolean()方法汹族,讀取一個字符串就使用getString()方法。這些get方法都接收兩個參數(shù)其兴,第一個參數(shù)是鍵顶瞒,傳入存儲數(shù)據(jù)時使用的鍵就可以得到相應(yīng)的值了;第二個參數(shù)是默認(rèn)值忌警,即表示當(dāng)前傳入的鍵找不到對應(yīng)的值時會以什么樣的默認(rèn)值進(jìn)行返回搁拙。
我們還是通過例子來實(shí)際體驗(yàn)一下吧,仍然是在SharedPreferencesTest項(xiàng)目的基礎(chǔ)上繼續(xù)開發(fā)法绵,修改activity_main.xml中的代碼箕速,如下所示:
? ? ? ? ? ? 可以看到,我們在還原數(shù)據(jù)按鈕的點(diǎn)擊事件中首先通過getSharedPreferences()方法得到了SharedPreferences對象朋譬,然后分別調(diào)用了它的getString()盐茎,getInt(),getBoolean()方法徙赢,取貨去前面所存儲的姓名字柠,年齡和是否已婚,如果沒有找到相應(yīng)的值狡赐,就會使用方法中傳入的默認(rèn)值來代替窑业,最后通過Log將這些值打印出來。
? ? ? ? ? ? 現(xiàn)在重新運(yùn)行一下程序枕屉,并點(diǎn)擊界面上Restore data按鈕常柄,然后查看logcat中的打印信息,如圖6.9所示搀擂。
? ? ? ? ? 所有值錢存儲的數(shù)據(jù)都成功讀取出來了西潘!,通過這例子哨颂,我們把SharedPreferences存儲的知識學(xué)寫完了喷市。相比之下SharedPreferences存儲確實(shí)要比文本存儲簡單方便了許多,應(yīng)用場景也多了不少威恼,比如很多應(yīng)用程序中的偏好設(shè)置功能其實(shí)都是用了SharedPreferences技術(shù)品姓,那么下面我們就來編寫一個記住密碼的功能,相信通過這個例子能夠加深你對SharedPreferences的理解沃测。
6.3.3 ? ? ? ?實(shí)踐記住密碼功能
6.4 ? ? ? ? ? SQlite數(shù)據(jù)庫存儲
? ? ? ? ?在剛開始接觸Android的時候缭黔,我甚至不敢相信,Android系統(tǒng)竟然是內(nèi)置了數(shù)據(jù)庫的蒂破!好吧馏谨!
? ? ? ? ?是我太孤陋寡聞了。SQlite是一款輕量級的關(guān)系關(guān)系型數(shù)據(jù)庫附迷,它的運(yùn)算數(shù)度非尘寤ィ快哎媚,占用資源很少,通常只需要幾百KB的內(nèi)存就足夠了喊儡,因而特別適合在移動設(shè)備上使用拨与。SQlite不僅支持標(biāo)準(zhǔn)的SQL語法,還遵循了數(shù)據(jù)庫的ACID事務(wù)艾猜,所以只要你以前使用國其他的關(guān)系型數(shù)據(jù)庫买喧,就可以很快上手SQlite。而SQlite又比一般的數(shù)據(jù)庫簡單很多匆赃,他甚至不用設(shè)置用戶名和密碼就可以使用淤毛。Android正是把這個功能極為強(qiáng)大的數(shù)據(jù)庫嵌入到了系統(tǒng)當(dāng)中,使用本地持久化的功能有了一次質(zhì)的飛躍算柳。
? ? ? ? ?前面我們所學(xué)的文件存儲和SharedPreferences存儲畢竟只適用于保存一些簡單的數(shù)據(jù)和建值對低淡,當(dāng)需要存儲大量復(fù)雜的關(guān)系型數(shù)據(jù)的時候,你就會發(fā)現(xiàn)以上兩種存儲方式很難應(yīng)付得了瞬项。比如我們手機(jī)的短信程序中可能會有很多個會話蔗蹋,每個會話中有包含了很多條信息內(nèi)容,并且大部分會話還可能各自對應(yīng)電話博中的某個聯(lián)系人囱淋。很難想象如何用文本或者SharedPreferences來存儲這些數(shù)據(jù)量大猪杭、結(jié)構(gòu)性復(fù)雜的數(shù)據(jù)吧?但是使用數(shù)據(jù)庫就可以做得到妥衣。那么我們就趕快來看一看胁孙,Android中的SQlite數(shù)據(jù)庫到底是如何使用的。
6.4.1 創(chuàng)建數(shù)據(jù)庫
? ? ? ? ? Android為了讓我們能夠鋼架方便的管理數(shù)據(jù)庫称鳞,專門提供了一個SQLiteOpenHelper幫助類,借助這個類可以非常簡單地對數(shù)據(jù)庫進(jìn)行創(chuàng)建和升級稠鼻。既然有好東西可以直接使用冈止,那我們自然要嘗試一下了,下面我就對SQLiteOPenHelper的基本用法進(jìn)行介紹候齿。
? ? ? ? ?首先你要知道SQLiteOpenHelper是一個抽象類熙暴,這意味著如果我們要想使用它的話,就需要創(chuàng)建一個自己的幫助類去繼承他慌盯。SQLiteOpenHelper中有兩個抽象方法周霉,分別是onCreat()和onUpgrade(),我們必須在自己的幫助類里面重寫這兩個方法亚皂,然后分別在這兩個方法中區(qū)實(shí)現(xiàn)創(chuàng)建俱箱、升級數(shù)據(jù)庫的邏輯。
? ? ? ? ? SQLiteOpenHelper中還有兩個非常重要的實(shí)例方法: getReadableDatabase()getWriteableDatabase()灭必。這兩個方法都可以創(chuàng)建或打開一個現(xiàn)有的數(shù)據(jù)庫(如果數(shù)據(jù)庫已經(jīng)存在則直接打開狞谱,否則創(chuàng)建一個新的數(shù)據(jù)庫)乃摹,并返回一個可對數(shù)據(jù)庫進(jìn)行讀寫操作的對象。不同的是跟衅,當(dāng)數(shù)據(jù)庫不可寫入的時候(如此磁盤空間已滿)孵睬,getReadableDatabase()方法返回的對象將以只讀的方式去打開數(shù)據(jù)庫,而getWriteableDatabase()方法則將出現(xiàn)異常伶跷。
? ? ? ? ? SQLiteOpenHelper中有兩個構(gòu)造方法可提供重寫掰读,一般使用參數(shù)少的一個構(gòu)造方法即可,這個構(gòu)造方法中接收4個參數(shù)叭莫,第一個參數(shù)是Context蹈集,這個沒什么好說的,必須要有它才能對數(shù)據(jù)庫進(jìn)行操作食寡。第二個參數(shù)是數(shù)據(jù)庫名雾狈,創(chuàng)建數(shù)據(jù)庫時使用的就是這里指定的名稱。第三個參數(shù)允許我們在查詢數(shù)據(jù)的時候返回一個自定義Curse抵皱,一般出入null善榛。第四個參數(shù)表示當(dāng)前數(shù)據(jù)庫的版本,可用于對數(shù)據(jù)庫進(jìn)行升級操作呻畸。構(gòu)建出SQLiteOpenHelper的實(shí)例之后移盆,再調(diào)用它的getReadableDatabase()或getWriteableDatabase()方法就能夠創(chuàng)建數(shù)據(jù)庫了,數(shù)據(jù)庫文件會存放在/data/data/<package name>/database/目錄下伤为。此時咒循,重寫的onCreat()方法特會得到執(zhí)行,所以通常會在這里去處理一些創(chuàng)建表的邏輯绞愚。
接下來我們希望創(chuàng)建一個名為BookStore,db的數(shù)據(jù)庫叙甸,然后在這個數(shù)據(jù)庫中新建一張Book表,表中有id(主鍵)位衩、作者裆蒸、價格、頁數(shù)糖驴、和書名等列僚祷。創(chuàng)建數(shù)據(jù)庫表當(dāng)然還是需要用建表語句的,
creat table Book (
id integer primary key autoincrement贮缕,
author text
price real
pages integer
name text
)
? ? ? ? ?只要你對SQL方法面的知識稍微有一些了解辙谜,上面的建表語句對你來說應(yīng)該不難吧。SQLite不像其他的數(shù)據(jù)庫擁有眾多繁雜的數(shù)據(jù)類型感昼,它的數(shù)據(jù)類型很賤装哆,integer 表示整形,real 表示浮點(diǎn)型,text 表示文本類型烂琴,bolb 表示二進(jìn)制類型爹殊。另外,上述建表語句中我們還使用了primary ? key將id列設(shè)為主鍵奸绷,并用autoincrement關(guān)鍵字表示id列是自增長的梗夸。
? ? ? ? 然后需要在代碼中去執(zhí)行這條SQL語句,才能完成創(chuàng)建表的操作号醉。新建MyDatabaseHelper類繼承自SQLiteOpenHelper反症,代碼如下所示:
可以看到,我們建表語句定義成了一個字符串常量畔派,然后在onCreat()方法中有調(diào)用了
SQLiteDatabase
的
execSQL
()方法執(zhí)行這條建表語句铅碍,并彈出一個Toas提示創(chuàng)建成功,這樣就可以保證在
數(shù)據(jù)庫創(chuàng)建完成的同時還能成功創(chuàng)建Book表:
布局文件很簡單线椰,就是加入了一個按鈕胞谈,用于創(chuàng)建數(shù)據(jù)庫.最后修改MainActivty中的代碼,如下所示:
? ? ? ? ? ? ?這里我們在onCreat()方法中構(gòu)建了一個MyDatabaseHelper對象憨愉,并且通過構(gòu)造函數(shù)的參數(shù)將數(shù)據(jù)庫名指定為BookStrore.db烦绳,版本號指定為1,然后在Creat database按鈕的點(diǎn)擊事件里調(diào)用getWriteableDatabase()方法配紫。這樣當(dāng)?shù)谝淮吸c(diǎn)擊Creat dataBase按鈕時径密,就會檢測到當(dāng)前程序中并沒有BookStrore.db這個數(shù)據(jù)庫,于是會創(chuàng)建該數(shù)據(jù)庫并調(diào)用MyDatabaseHelper中的onCreat()方法躺孝,這樣BOOK表也就得到了創(chuàng)建享扔,然后就會彈出一個Toast提示數(shù)據(jù)庫創(chuàng)建成功。再次點(diǎn)Creat database按鈕時植袍,會發(fā)現(xiàn)此時已經(jīng)存在BookStore.db數(shù)據(jù)庫了惧眠,因此不會再創(chuàng)建一次
? ? ? ? ? ? 現(xiàn)在就可以運(yùn)行一下代碼了,在程序主界面點(diǎn)擊Creat database按鈕于个,結(jié)果如圖6.12所示:
? ? ? ? ? ? 此時BookStore.db數(shù)據(jù)庫和Book表應(yīng)該都已經(jīng)創(chuàng)建成功了锉试,因?yàn)楫?dāng)你再次點(diǎn)擊Create database按鈕時,不會再有Toast彈出览濒。可以又回到了之前的那個老問題拖云,怎樣才能證實(shí)它們的確創(chuàng)建成功了贷笛?如果還是使用File Explorer,那么最多你只能看到database目錄下出現(xiàn)一個BookStore.db文件宙项,Book表示無法通過File Explorer看到的乏苦。因此這次我們準(zhǔn)備換一種查看方式,使用adb shell來對數(shù)據(jù)庫和表的創(chuàng)建情況進(jìn)行檢查。
? ? ? ? ? ? adb 是Android SDK中自帶的一個調(diào)試工具汇荐,使用這個工具可以直接對連接在電腦上手機(jī)或模擬器進(jìn)行調(diào)試操作洞就。他存在sdk的platform-tools目錄下,如果想要在命令中使用這個工具掀淘,就需要先把他的路徑配置到環(huán)境里旬蟋。
如果你是用的是Windows系統(tǒng),可以點(diǎn)擊計(jì)算機(jī)---->屬性------>高級系統(tǒng)設(shè)置-------->環(huán)境變量革娄,然后在系統(tǒng)變量里找到Path并點(diǎn)擊編輯倾贰,將platform-tools目錄配置進(jìn)去,如圖6.13所示拦惋。