Android系統中主要提供了3種方式用于簡單地實作資料持久化功能,即檔案存盤、SharePrefererence存盤以及資料庫存盤,當然,除了這三種方式之外,你還可以將資料保存在手機的SD卡中,不過使用檔案、SharePreference或資料庫來保存資料會相對更簡單一些,而且比起將資料保存在SD卡中會更安全,
檔案存盤:
檔案存盤是Android中最基本的一種資料存盤方式,它不對存盤的內容進行任何的格式化處理,所有資料都是原封不動地保存在檔案當中的,因而它比較適合用于存盤一些簡單的文本資料或二進制資料,如果你想使用檔案存盤的方式來保存一些較為復雜的文本資料,就需要定義一套自己的個格式規范,這樣可以方便之后將資料從檔案中重新決議出來,
將資料存盤到檔案中:
Context類中提供了一個openfileoutput方法,可以用于將資料存盤到指定的檔案中,這個方法有兩個引數,第一個引數是檔案名,在檔案創建的時候使用的就是這個名稱,注意這里指定的檔案名不可以包含路徑,因為所有的檔案都是默認存盤到\data\data<package name>\files\目錄下的,第二個引數是檔案的操作模式,主要有兩種模式可以選擇,MODE_PRIVATE和MODE_APPEND,其中第一個是默認的操作模式,表示當指定同樣檔案名的時候,所寫入的內容將會覆寫原檔案中的內容,而第二個操作模式則表示如果該檔案已經存在,就往檔案里面追加內容,不存在就創建檔案,
openfileoutput方法回傳的是一個fileoutputstream物件,得到了這個物件之后就可以使用java流的方式將資料寫到檔案中了,以下是一段簡單的代碼實體,直接拉過來
這里對java流解釋一下,通過openfileoutput方法能夠得到一個fileoutputstream物件,然后借助它構建出一個outputstreamwriter物件,在截至使用outputstreamwriter構建出一個bufferedwriter物件,這樣就可以通過bufferedwriter來將文本內容寫入到檔案中了,




在oncreate方法中獲取了edittext的實體,然后重寫了ondestroy方法,這樣就可以保證在活動銷毀之前一定會呼叫這個方法,再ondestroy方法中獲取到edittext中輸入的內容,并呼叫save方法把輸入的內容存盤到檔案中,檔案命名為data,

從檔案中讀取資料
類似于將資料存盤到檔案中,Context類中還提供了一個openfileinput方法,用于從檔案中讀取資料,這個方法要比openfileoutput簡單一些,它只接受一個引數,即要讀取的檔案名,然后系統會自動到\data\data<package name>\files\目錄下去加載這個檔案,并回傳一個fileinputstream物件,得到了這個物件之后再通過java流的方式就可以將資料讀取出來了,下面是簡單的代碼演示
修改活動中的代碼
這里在oncreate方法中呼叫load方法來讀取檔案中存盤的文本內容,如果讀取的內容不會null,就呼叫edittext的settext方法將內容填充的edittext里,并呼叫setSelection方法將輸入游標移動到文本的末尾位置以便于繼續輸入,然后彈出一句還原成功的提示,
代碼在對字串進行非空判斷的時候使用了TextUtiles.isEmpty方法,這是一個非常好用的方法,他可以一次性進行兩種空值的判斷,當傳入字串等于null或者等于空字串時,這個方法都會回傳true,從而使得我們不需要先單獨判斷這兩種空值再使用邏輯運算子連接起來了,
SharePreferences存盤
不同于檔案的存盤方式,SharePreferences是使用鍵值對的方式來存盤資料的,也就是說當保存一條資料的時候,需要給這條資料提供一個對應的鍵,這樣在讀取資料的時候就可以通過這個鍵,而且SharePreferences還支持多種不同的資料型別春促,如果存盤的資料型別是整形,納米讀取出來的資料也是整性的;如果存盤的資料是一個字串,納米讀取出來的資料仍是字串,
將資料存盤到SharePreferences中
要使用SharePreferences儲存資料,首先需要獲取它的物件,android中主要提供了三種方法用于得到物件
1.Context類中的getSharePreferes方法
此方法接受兩個引數,第一個引數用于指定SharePreferes檔案的名稱,如果指定的檔案不存在則會創建一個,SharePreferences檔案都是存放在data\data<package name>\shared_prefs\目錄下的,第二個引數用于指定操作模式,目前只有MODE_PRIVATE著一種模式可選,它是默認的操作模式,和直接傳入0效果是相同的,表示只有當前的應用程式才可以對這個SharePreferences檔案進行讀寫,其他幾種操作模式均已被廢棄,
2.Activity類中的getPreferences方法
這個方法和Context中的getSharedPreferences方法很相似,只不過它只接收一個操作模式引數,因為使用這個方法時會自動將當前活動的類名作為SharedPrefereces的檔案名,
3.PreferenceManager類中的getDefaultSharedPreferences方法
這是一個靜態方法,它接受一個Context引數,并自動使用當前應用程式的包名作為前綴來命名SharedPreferences檔案,得到了SharedPreferences物件之后,就可以開始向SharedPreferences檔案中存盤資料了,主要可以分三步實作,
(1)呼叫SharedPreferences物件的edit方法來獲取一個SharedPreferences.Editor物件
(2)向SharedPreferences.Editor物件中添加資料,比如添加一個布爾型資料就使用putBoolean方法,添加一個字串就要用putString方法
(3)呼叫apply方法將添加的資料提交,從而完成資料存盤操作



從SharedPreferences中讀取資料
從SharedPreferences檔案中讀取資料更加簡單,SharedPreferences物件中提供了一系列的get方法,用于對存盤資料進行讀取,每種get方法都接受兩個引數,第一個引數是鍵,傳入存盤資料時使用的鍵就可以得到相應的值了;第二個引數是默認值,即表示當傳入的鍵找不到對應的值會以什么樣的默認值進行回傳,


實作記住密碼功能



首先在oncreate方法中獲取到了SharedPreference物件,然后呼叫它的getBoolean方法去獲取remember_password這個鍵對應的值,一開始當然不存在對應的值,所以會使用默認值false,這樣就什么都不會發生,接著再登陸成功之后,會呼叫CheckBos的isChecked方法倆檢查復選框是否被選中,如果被選中了,則表示用戶想要記住密碼,這時將remeber_password設定為true,然后把account和password對應的值都存入到SharedPreferences檔案當中并提交,如果沒有被選中,就簡單的呼叫一下clear方法,將SharedPreferences檔案中的資料全部清除掉,
AndroidSQLite資料庫存盤
SQLiteOpenHelper幫助類,它是一個抽象類,有兩個抽象方法,分別是onCreate和onUpgrade,我們必須在自己的幫助類中重寫這兩個方法,然后分別在這兩個方法中去實作創建、升級資料庫的邏輯,
SQLiteOpenHelper中還有兩個非常重要的實體方法:getReadableDatabase和getWritableDatabase,這兩個方法都可以創建或打開一個現有的資料庫(如果資料庫已經存在則直接打開,否則創建一個新的資料),并回傳一個可對資料庫進行讀寫操作的對線,不同的是,當資料庫不可寫入的時候(如磁盤空間已滿),getReadableDatabase方法回傳的物件以只讀的方式打開資料庫,而getW方法則將出現例外,SQLiteOH中有兩個構造方法可供重寫,一般使用引數少一點的那個構造方法,這個構造方法接受四個引數,第一個是Context,第二個是資料庫名,第三個是允許我們在查詢資料的時候回傳一個自定義的Cursor,一般都是傳入null第四個引數表示當前資料庫的版本號,可用于對資料庫進行升級操作,構建出SQLOH的實體后,在呼叫gRD或者gWD方法就可以創建資料庫了,資料庫檔案會存放在

目錄下,此時重寫的onCreate方法也會得到執行,所以通常會在這里去處理一些創建表的邏輯,
例子:
新建DatabaseTest專案,創建BookStore.db資料庫,在資料庫中新建Book表,id、作者、價格、頁數、書名等列,表的創建陳述句為
需要在代碼中去執行sql陳述句,新建MydatabaseH去繼承SQLOH

在布局中新建一個Btn,用于創建資料庫,修改活動中的代碼

然后我們使用adb shell來對資料和表的創建情況進行檢查,
adb是Android SDK中自帶的一個除錯工具,使用這個工具可以直接對鏈接在電腦上的手機或者模擬器進行除錯操作,它存放在sdk的platform-tools目錄下,如果想要在命令列中使用這個工具,就需要先把它的路徑配置到環境變數里,Path中哦,把platform-tools目錄配置進去,環境變數配置好后,就可以使用adb工具了,打開命令列界面,輸入adb shell,就會進入到設備的控制臺,然后使用cd命令進入到/data/data/com.example.databasetest/databases/目錄下,并使用ls命令查看到該目錄里的檔案,這個目錄下出現了兩個資料庫檔案,一個是我們創建的BS.db,而另一個BookStore.db-journal則是為了讓資料庫能夠支持事務而產生的臨時日志檔案,通常情況下這個檔案的大小都是0位元組,
接下來使用sqlite命令打開資料庫,只需要鍵入sqlite3,后面加上資料庫名即可,然后對表進行管理,先看下目錄中有哪些表,鍵入.table命令,此時資料庫中有兩張表,android_metadata表是每個資料庫中都會自動生成的,不用管,另一張Book表就是我們在MyDatabaseHelper中創建的了,這里還可以通過**.schema命令來查看他們的建表陳述句,之后鍵入.exit或者.quit命令可以退出資料庫的編輯,再鍵入exit命令**就可以推出設備控制臺了,
升級資料庫
MyDatabaseHelper中還有一個空方法,onUpgrade方法是對于資料庫進行升級的,他在整個資料庫管理作業當中起著非常重要的作用,
目前DatabaseTest專案中已經有一張Book表用于存放書中的各種詳細資料,我們還想再添加一張Category表用于記錄圖書的分類,
建表陳述句

但現在表并沒有創建成功,原因是,此時BS資料庫已經存在了,之后不管我們怎么點擊按鈕,MydatabaseHelper中的onCreate方法都不會再次執行,因此新添加的表也就無法得到創建了,解決這個問題的方法只需要先將程式卸載掉,然后重新運行,這時BookStore.db資料庫已經不存在了,再點擊然后呼叫oncreate方法,category表就可以創建成功了,不過通過卸載程式的方式來新增一張表毫無疑問是很極端的做法,其實我們只需要巧妙的運用SQLiteOpenHelper的升級功能就可以輕松解決這個問題,修改MydatabaseHelper中的方法,
drop陳述句,是如果發現資料庫中已經存在Book表或Category表了,就將這兩張表洗掉掉,然后再呼叫onCreate方法重新創建,這里先將已經存在的表洗掉掉,因為如果在創建表時發現這張表已經存在了,就會直接報錯,接下來的問題時如何讓onUpgrade方法能夠執行,SQLiteSOpenHepler的構造方法中第四個引數,他表示資料庫的版本號,之前我們傳入的是1,現在只要傳入一個比1大的數,就可以讓onUpgrade方法得到執行了,修改活動中的代碼,

添加資料,四種操作CRU,分別是添加Create,查詢Retrieve,更新Update,洗掉delete,每一種操作又各自對應了一種SQL命令,getReadableDatabase或者getWritabledatabase方法是可以用于創建和升級資料庫的,不僅如此,這兩個方法還都會回傳一個SQLiteDatabase物件,借助這個物件就可以對資料進行CRUD操作了,SQLiteDatabase中提供了一個insert方法,用來添加資料,它接受三個引數,第一個引數是表名,第二個引數用于在未指定添加資料的情況下給某些可為空的列自動賦值NULL,一般我們用不到這個功能,直接傳入null,第三個引數是一個ContentValues物件,它提供了一系列put方法多載,用于向ContenValues中添加資料,只需要將表中每個列明以及相應的帶添加資料傳入即可,
例子
還是新建一個bun用來寫添加資料的邏輯,
修改活動中代碼

這里只對Book表里其中四列的資料進行了組裝,id那一列并沒給它賦值,這是因為在前面創建表的時候,我們將id設定為自增長了,它的值會在入庫的時候自動生成,所以不需要手動賦值,
更新資料:update方法,有四個引數,第一個引數是表名,第二個引數是ContenValues物件,要把更新資料在這里組裝進去,第三第四個引數用于約束更新某一行或某幾行中的資料,不指定的話默認就是更新所有行,



第三個引數對應的是SQL陳述句中的where部分,表示更新所有name等于?的行,而?是一個占位符,可以通過第四個引數提供的一個字串陣列為第三個引數中的每個占位符指定相應的內容,
洗掉資料,delete,第一個引數是表明,第二、第三個引數是用于約束洗掉某一行或者某幾行的資料,不指定默認所有行,


這里的意思是洗掉頁數大于500的書,
查詢資料,query方法,最短一個方法多載也需要七個引數,第一個是表明,第二個是指定去查詢哪幾列,如果不指定則則默認查詢所有列,第三第四個約束用于查詢某一行或者某幾行的資料,不指定則默認查詢所有行,第五個引數指定需要去group by的列,不指定則表示不對查詢結果進行group by操作,第六個引數用于對group by之后的資料進行進一步的過濾,不指定則表示不過濾,,第七個引數用于指定查詢結果的排序方式,不指定則表示使用默認的排序方式,

引數很多,但多數情況下只需要傳入少數幾個引數就可以完成查詢操作了,呼叫query方法后會回傳一個Cursor物件,查詢到的所有資料都將從這個物件中取出,

moveToFirst方法將資料的指標移動到第一行的位置,然后進入了一個回圈當中,去遍歷查詢到的每一行資料,這個回圈可以通過Cursor的getColumnIndex方法獲取到某一列在表中對應的位置索引,
下面列出這幾種操作的代碼,
1、SQLiteDataBase物件的query()介面
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs,String groupBy, String having,String orderBy,String limit)
示例:
ContentValues cv = new ContentValues();
String[] args = {String.valueOf("a")};
query("user",new String[] { "username","password" },"username=?", args,null,null,null, null);
2、SQLiteDataBase物件的insert()介面:
publiclong insert (String table, String nullColumnHack, ContentValues values)
示例:
ContentValues cv = new ContentValues();
cv.put("username", "lanxiaofang");
cv.put("password", "123456");
insert("user", null,cv);
3、SQLiteDataBase物件的update()介面:
publicint update (String table, ContentValues values, String whereClause, String[] whereArgs)
示例:
ContentValues cv = new ContentValues();
cv.put("username", "lanxiao");
cv.put("password", "123456");
String[] args = {String.valueOf("lanxiaofang")};
update("user",cv, "username=?",args)
4、SQLiteDataBase物件的delete()介面:
publicint delete (String table, String whereClause, String[] whereArgs)
示例:
ContentValues cv = new ContentValues();
String[] args = {String.valueOf("lanxiaofang")};
delete("user", "username=?",args);
使用LitePal操作資料庫
LitePal是一款開源的Android資料庫框架,它采用了物件關系映射(ORM)的模式,并將我們平時開發最常用到的一些資料庫功能進行了封裝,使得不用撰寫一行SQL陳述句就可以完成各種建表和增刪改查的操作,LitePal的專案主頁上也有詳細的使用檔案,地址是:https://github.com/LitePalFramework/LitePal,
配置LitePal:
通常使用開源庫需要下載開源庫的jar包或者原始碼,再集成到我們的專案當中去,現在大多的開源專案都會將版本提交到jcenter上,我們只需要app/build.gradle檔案中宣告該開源庫的參考就可以了,在denpendencies閉包中添加如下內容
1.3.2是版本號的意思,最新的版本號可以到LitePal的專案主頁上去查看,
這樣就成功把LitePal成功引入到當前專案中了,接下來需要配置litepal.xml檔案,右擊
創建一個assets目錄,然后再assets目錄下再新建一個litepal.xml檔案,接著編輯litepal.xml檔案中的內容,如下
其中標簽用于指定資料庫名,version標簽用于指定資料庫版本號,list標簽用于指定所有的映射模式,
最后需要配置一下LitePalApplication,修改AndroidMainfest.xml中的代碼,如下

這里將專案的application配置為org.litepal.LitePalApplication,這樣才能讓LitePal的所有功能都可以正常作業,關于application先知道必須這么寫就可以了,
創建和升級資料庫
之前創建資料庫時通過自定義一個類繼承SQLiteOpenHelper,然后在onCreate方法中撰寫建表陳述句來實作的,而使用LitePal就不用這么麻煩了,
LitePal采取的是物件關系映射(ORM)的模式,簡單點說,我們使用的編程語言時面向物件語言,而使用的資料庫則是關系型資料庫,那么將面向物件的語言和面向關系的資料庫之間建立一種映射關系,這就是物件關系映射了,它賦予了我們一個強大的功能,就是可以用面向物件的思維來操作資料庫,而不再和SQL陳述句大交到了,
比如我們創建Book表,需要先分析表中應該包含哪些列,然后再撰寫出一條建表陳述句,最后在自定義的SQLiteOpenHelper中去執行這條建表陳述句,但是使用LitePal,你就可以用面向物件的思維來實作同樣的功能了,定義一個Book類,如下

這是一個典型的java bean,
JavaBean是一個遵循特定寫法的Java類,它通常具有如下特點: 這個Java類必須具有一個無參的建構式 屬性必須私有化,
私有化的屬性必須通過public型別的方法暴露給其它程式,并且方法的命名也必須遵守一定的命名規范,
Book類就會對應資料庫中的Book表,而類中的每一個欄位分別對應了表中的每一個列,這就是物件關系映射最直觀的體驗,
接下來我們還需要將Book類添加到映射模型串列當中,修改litepal.xml中的代碼,

這里使用mapping標簽來宣告我們要配置的映射模型類,注意一定要使用完整的類名,不管有多少模型類需要映射,都使用同樣的方式配置在list標簽下即可,
現在修改活動中的代碼

其中,呼叫Connector.getDatabase方法就是一次最簡單的資料庫操作,只要點擊按鈕資料庫就自動創建完成了,可以通過adb shell來查看一下資料庫創建的情況,使用sqlite3命令打開BookStore.db檔案,再使用.schema命令來查看建表陳述句,這里有三張表的建表陳述句,其中android_metadata表仍然不用管,table_schema表時LitePal內部使用的,我們也可以直接忽視,book表就是我們定義的Book類以及類中的欄位來自動生成的,
之前使用SQLiteOpenHelper來升級資料庫的方式雖然說功能實作了,但是升級資料庫的時候需要把之前的表drop掉,然后再重新創建才行,這其實是一個非常嚴重的問題,因為這樣會造成資料丟失,每當升級一次資料庫,之前表中的資料就全都沒了,需要通過復雜的邏輯控制來避免這種情況,但是維護成本很高,而有了LitePal,這些就都不再是問題了,使用LitePal來升級資料庫非常簡單,只需要修改你想改的內容,然后將版本號加1就可以啦,
比如我們想要向Book表中添加一個press(出版社)列,直接修改Book類中的代碼,添加一個press欄位即可,如下
與此同時,如果想添加一張Category表,那么只需要新建一個Category類就可以了,代碼如下

改完了所有想改的東西,只需要記得將版本號加一就可以了,當然由于這里還添加了一個新的模型類,因此也需要將它添加到映射模型串列中,修改litepal.xml中的代碼,如下
這樣就成功啦,
使用LitePal添加資料
回顧一下之前添加資料的方法,我們需要創建出一個ContentValues物件,然后將所有要添加的資料put到這個ContenValues物件當中,最后再呼叫SQLiteDatabase的insert方法將資料添加到資料庫表當中,而使用LitePal只需要創建出模型類的實體,再將所有要存盤的資料設定好,最后呼叫一下save方法就可以了,
下面開始實作,觀察現有的模型類,他們都沒有繼承結構,LitePal進行表管理操作時不需要模型類有任何的繼承結構,但是進行CRUD操作時就不行了,必須要繼承自DataSupport類才行,因此這里我們需要先把繼承結構給加上,修改Book類中的代碼,
接著開始向Book表中添加資料,修改MainActivity中的代碼
這個save方法是從DataSupport中繼承來的,除了save方法,DataSupport類還給我提供了豐富的CRUD方法,
更新資料
最簡單的一種更新方式就是對已經存盤的物件重新設值,然后重新呼叫save方法即可,那么一寸處的物件,對于LitePal來說,物件是否已存盤就是根據呼叫model.isSaved方法的結果來判斷的,回傳true就表示已經存是,回傳false就是為存盤,那么什么時候會回傳true或false呢,
實際上只有在兩種情況下model.isSaved方法才會回傳true,一種情況是已經呼叫過model.save方法去添加資料了,此時model會被認為是已經存盤的物件,另一種情況是model物件是通過LitePal提供的查詢API查出來的,由于是從資料庫中查到的物件,因此也會被認為是已經存盤的物件
更新例子:

先new出一個實體,再呼叫方法來設定要更新的資料,最后呼叫updateAll方法去執行更新操作,注意updateAll方法中可以指定一個條件約束,和SQLiteDatabase中update方法的where引數部分有點類似,但更加簡潔,如果不指定則默認所有,
在使用updateAll方式,當你想吧一個欄位的值更新成默認值時,是不可以使用上面的方式來set資料的,我們都知道,在java中任何一種資料型別的欄位都會有默認值,例如int默認值是0 ,new出一個Book物件時,其實所有欄位都已經被初始化成默認值了,因此如果我們想吧資料庫表中的pages列更新成0,直接呼叫book.setPages(0)這個方法是不可以的,因為即使不呼叫這行代碼,pages欄位本身也是0,LitePal此時是不會對這個列進行更新的,對于所有想要將為資料更新成默認值的操作,LitePal同意提供了一個setToDefault方法,然后傳入相應的列名就可以實作,
使用LitePal洗掉資料
這里呼叫了deleteAll方法來洗掉資料,其中第一個引數用于指定洗掉那張表的資料,Book.class就是洗掉Book表中的資料,后面的引數用于指定約束條件,
查詢


查詢表中第一條資料

查詢最后一條資料
同時LitePal爺支持原生的SQL來進行查詢,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/258982.html
標籤:其他
上一篇:Auto.js微信搶紅包腳本
