摘要:所謂的,其實(shí)就是數(shù)據(jù)庫(kù)的基本操作,代表,代表,代表,則代表。數(shù)據(jù)庫(kù)好幫手上面已經(jīng)給出了創(chuàng)建表并定義字段的方法,在別的地方它可以在終端或者腳本中運(yùn)行,在世界里自然要在類(lèi)中大展宏圖。
一 前言
經(jīng)常聽(tīng)到已經(jīng)工作的程序員說(shuō)每天的工作很無(wú)聊,總是一些CURD操作,沒(méi)什么技術(shù)含量,對(duì),今天我們就要勇敢的探索一下這所謂的“無(wú)聊工作”--CURD,并想辦法讓它有趣起來(lái)。所謂的CURD,其實(shí)就是數(shù)據(jù)庫(kù)的基本操作,C代表create,U代表update,R代表read,D則代表delete。寫(xiě)過(guò)后臺(tái)腳本的朋友對(duì)這個(gè)應(yīng)該很熟悉,你就可以隨便翻翻啦,而不太了解數(shù)據(jù)庫(kù)操作的朋友,我在這里拋磚引玉,講一下怎么將內(nèi)存中的數(shù)據(jù)保存到本地?cái)?shù)據(jù)庫(kù)中,您看完后可以更加深入的去尋找一些資料學(xué)習(xí),千萬(wàn)要記得不管別人說(shuō)什么無(wú)聊或者沒(méi)有技術(shù)含量,我們還是要一步一個(gè)腳印,堅(jiān)持敲下去!
二 創(chuàng)建伴隨類(lèi)前面說(shuō)了我們要把這簡(jiǎn)單的操作講的有趣些,那我就玩點(diǎn)套路,不直接講API,先來(lái)看一個(gè)類(lèi):
package com.aristark.note.database; public class NoteDbScheme { public static final class NoteTable{ public static final String name = "notes"; public static final class Cols{ public static final String UUID = "uuid"; public static final String TITLE = "title"; public static final String CONTENT = "content"; public static final String DATE = "date"; public static final String TAG = "tag"; } } }
類(lèi)的名字叫NoteDbScheme,表明它是一個(gè)關(guān)于“計(jì)劃”的類(lèi),而且和database少不了干系,再來(lái)回憶Note這個(gè)類(lèi):
public class Note { private UUID uuid; private String title; private String content; private Date date; private String tag; public Note(){ uuid = UUID.randomUUID(); date = new Date(); } public UUID getUuid() { return uuid; } public Date getDate() { return date; } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } public void setContent(String content) { this.content = content; } public String getContent() { return content; } public void setTag(String tag) { this.tag = tag; } public String getTag() { return tag; } }
很容易看出來(lái)Note類(lèi)里的私有字段和NoteDbScheme里常量的值是一致的,言下之意,我們可以從數(shù)據(jù)庫(kù)里取值賦給Note類(lèi)中的字段,也可以把Note類(lèi)中字段的值存入數(shù)據(jù)庫(kù)。再回憶一下之前我們是怎么用Note類(lèi)的,我們?cè)贜oteLab創(chuàng)建了一個(gè)泛型為Note的ArrayList,然后通過(guò)NoteListActivity把它渲染到layout,也就是用戶(hù)的界面上,這樣看來(lái),Note類(lèi)隱隱約約好像作為一個(gè)溝通的橋梁(其實(shí)了解MVC模式的朋友應(yīng)該很好理解)。
三 創(chuàng)建數(shù)據(jù)庫(kù)1.sql簡(jiǎn)介:了解sql知識(shí)點(diǎn)這里
了解sqlite知識(shí)點(diǎn)這里
懶得看的就直接看這段sql語(yǔ)句,強(qiáng)行接受我的解釋就行了:
create table note( _int integer primary key autoincrement, uuid text, title text, content text, date text, tag text )
這段SQL語(yǔ)句的意思是,創(chuàng)建一個(gè)名叫“note”的表,包含6個(gè)字段,以第一個(gè)字段為例,_int為字段名,integer為字段類(lèi)型,primary key autoincrement表示它是主鍵并自增。請(qǐng)大家記住這個(gè)套路。
2.SQLiteOpenHelper---數(shù)據(jù)庫(kù)好幫手
上面已經(jīng)給出了創(chuàng)建表并定義字段的方法,在別的地方它可以在終端或者腳本中運(yùn)行,在Android世界里自然要在類(lèi)中大展宏圖。如果你的英語(yǔ)還可以請(qǐng)你打開(kāi)Android->sdk>doc,在官方文檔中搜索SQLiteOpenHelper,你會(huì)發(fā)現(xiàn)你要做的這個(gè)類(lèi)基本上已經(jīng)幫你封裝好了,你要做的就是繼承它,并依照你的需求去敲敲打打就行。好,來(lái)寫(xiě)代碼:
public class NoteBaseHelper extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
這里需要覆寫(xiě)的onCreate方法就是我們創(chuàng)建表的地方,當(dāng)NoteBaseHelper被實(shí)例化時(shí),它會(huì)自動(dòng)檢測(cè)數(shù)據(jù)庫(kù)中有沒(méi)有note這個(gè)表,如果沒(méi)有就調(diào)用該方法。所以我們把剛剛的sql語(yǔ)句寫(xiě)進(jìn)去:
@Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table " +NoteDbScheme.NoteTable.name+"(" + "_id integer primary key autoincrement," +NoteDbScheme.NoteTable.Cols.UUID+"," +NoteDbScheme.NoteTable.Cols.TITLE+"," +NoteDbScheme.NoteTable.Cols.CONTENT+"," +NoteDbScheme.NoteTable.Cols.DATE+"," +NoteDbScheme.NoteTable.Cols.TAG +")" ); }
這里寫(xiě)的和上面其實(shí)是完全一樣的,只不過(guò)我們是用NoteDbScheme中的常量代替了字符串而已,這樣做的好處是如果以后表中的字段需要變更的話(huà)我們只要在NoteDbScheme中變更就行了,而不需要?jiǎng)舆@里的代碼。另一個(gè)需要覆寫(xiě)的onUpgrade在數(shù)據(jù)庫(kù)需要更新的時(shí)候調(diào)用。我們?cè)偬砑觾蓚€(gè)常量來(lái)標(biāo)記數(shù)據(jù)庫(kù)的名字和版本:
public class NoteBaseHelper extends SQLiteOpenHelper { public static final int VERSON = 1; public static final String DATABASE_NAME = "NoteBase"; @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table " +NoteDbScheme.NoteTable.name+"(" + "_id integer primary key autoincrement," +NoteDbScheme.NoteTable.Cols.UUID+"," +NoteDbScheme.NoteTable.Cols.TITLE+"," +NoteDbScheme.NoteTable.Cols.CONTENT+"," +NoteDbScheme.NoteTable.Cols.DATE+"," +NoteDbScheme.NoteTable.Cols.TAG +")" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
最后別忘了創(chuàng)建NoteBaseHelper的構(gòu)造方法:
public NoteBaseHelper(Context context) { super(context,DATABASE_NAME,null,VERSON); }
DATABASE_NAME和VERSON就是我們剛才定義過(guò)的。
3.創(chuàng)建數(shù)據(jù)庫(kù)和表
前面我們分析了,我們用NoteLab類(lèi)將數(shù)據(jù)渲染到前臺(tái)用戶(hù)界面,同樣的我們也用它來(lái)與后臺(tái)數(shù)據(jù)庫(kù)交互,先來(lái)回顧一下NoteLab類(lèi):
public class NoteLab { private static NoteLab sNoteLab; //for the global use private ArrayListnotes; private NoteLab(Context context){ notes = new ArrayList (); //generate 100 Note Objects // for (int i=0;i<100;i++){ // Note note = new Note(); // note.setTitle("this is title "+i); // note.setContent("this is content "+i+"balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala "); // notes.add(note); // } } public static NoteLab getNoteLab(Context context){ if (sNoteLab == null){ sNoteLab = new NoteLab(context); } return sNoteLab; } public ArrayList getNotes() { return notes; } public void addNote(Note note){ notes.add(note); } public Note getNote(UUID uuid){ for (Note note : notes){ if (note.getUuid().equals(uuid)){ return note; } } return null; } }
每個(gè)方法的用途都可以通過(guò)命名來(lái)體現(xiàn),實(shí)在看不懂的翻看我前面兩篇文章就行了。
public SQLiteDatabase getWritableDatabase ()
Added in API level 1
Create and/or open a database that will be used for reading and writing. The first time this is called, the database will be opened and onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int) and/or onOpen(SQLiteDatabase) will be called.
Once opened successfully, the database is cached, so you can call this method every time you need to write to the database. (Make sure to call close() when you no longer need the database.) Errors such as bad permissions or a full disk may cause this method to fail, but future attempts may succeed if the problem is fixed.
Database upgrade may take a long time, you should not call this method from the application main thread, including from ContentProvider.onCreate().
Returns
a read/write database object valid until close() is called
Throws
SQLiteException if the database cannot be opened for writing
這是Google官方文檔中關(guān)于SQLiteOpenHelper類(lèi)的一個(gè)方法,用來(lái)創(chuàng)建或者打開(kāi)一個(gè)數(shù)據(jù)庫(kù),好,我們就在NoteLab類(lèi)的構(gòu)造方法中來(lái)使用這個(gè)方法:
public class NoteLab { private static NoteLab sNoteLab; //for the global use private ArrayListnotes; private Context context; private SQLiteDatabase database; private NoteLab(Context context){ notes = new ArrayList (); database = new NoteBaseHelper(context).getWritableDatabase(); //generate 100 Note Objects // for (int i=0;i<100;i++){ // Note note = new Note(); // note.setTitle("this is title "+i); // note.setContent("this is content "+i+"balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala balabalabalabalalabalabalabalabalala "); // notes.add(note); // } } ...... }
這樣我們?cè)趧?chuàng)建NoteLab的同時(shí)也就創(chuàng)建了NoteBase數(shù)據(jù)庫(kù)和note表。好,編譯,運(yùn)行,這時(shí)候打開(kāi)Android Device Monitor(Android Studio問(wèn)號(hào)左邊的小機(jī)器人按鈕)
在Android中,所有App的本地?cái)?shù)據(jù)庫(kù)都在data->data下,找到我們這個(gè)應(yīng)用的包名之下的databases目錄下,我們看到了NoteBase數(shù)據(jù)庫(kù),說(shuō)明我們成功創(chuàng)建了note表!
插入數(shù)據(jù)無(wú)非就是將一組鍵值對(duì)提交給操作數(shù)據(jù)的API,而這里的鍵值對(duì)就是以ContentValues來(lái)組裝的(大家在這里一定要去官方文檔搜到這個(gè)類(lèi)好好讀一下,不然可能會(huì)在這里卡?。?,我們現(xiàn)在在NoteLab類(lèi)中添加如下方法:
private ContentValues getValues(Note note){ ContentValues values = new ContentValues(); values.put(NoteDbScheme.NoteTable.Cols.UUID,note.getUuid().toString()![圖片描述][5]); values.put(NoteDbScheme.NoteTable.Cols.TITLE,note.getTitle()); values.put(NoteDbScheme.NoteTable.Cols.CONTENT,note.getContent()); values.put(NoteDbScheme.NoteTable.Cols.DATE,note.getDate().toString()); values.put(NoteDbScheme.NoteTable.Cols.TAG,note.getTag()); return values; }
代碼很容易讀,put方法接受的就是key--value對(duì),這里再一次用到了NoteDbScheme類(lèi),是不是覺(jué)得很奇妙很方便?現(xiàn)在我們改寫(xiě)之前的addNote方法:
public void addNote(Note note){ // notes.add(note); ContentValues values = getValues(note); database.insert(NoteDbScheme.NoteTable.name,null,values); }
這里著重掌握insert方法,第一個(gè)參數(shù)接受將要插入的表名,第三個(gè)參數(shù)就是我們需要組裝的ContentValues,第二個(gè)參數(shù)是關(guān)于插入空記錄的相關(guān)設(shè)置,大家可以去查看文檔。好,編譯,運(yùn)行:
點(diǎn)擊右上角加號(hào),輸入數(shù)據(jù)幾組數(shù)據(jù)
很遺憾我現(xiàn)在并不會(huì)檢驗(yàn)數(shù)據(jù)是否寫(xiě)進(jìn)表,不管了繼續(xù)寫(xiě)代碼,去把數(shù)據(jù)庫(kù)的記錄讀出來(lái)!
寫(xiě)了這么多有點(diǎn)寫(xiě)不下去了,不知道你是不是也看不下去了,你心里肯定想這太冗雜了(誰(shuí)讓咱們使用java寫(xiě)android呢,隨便寫(xiě)寫(xiě)就感覺(jué)好多的樣子,但是換個(gè)角度想我們可以對(duì)外吹我們的代碼量很多啊哈哈,雖然并沒(méi)有什么卵用)。扯店?duì)僮?,大家回顧一下C語(yǔ)言中的指針和java語(yǔ)言中的引用(句柄?handle?指針?),或者是數(shù)組中的索引,我們會(huì)發(fā)現(xiàn)這些重要的抽象對(duì)于我們操作數(shù)據(jù)是很有用的,對(duì)了,在Android我們有Cursor(中文意思是游標(biāo),對(duì),就是游標(biāo)卡尺的那個(gè)游標(biāo)),我們可以變相的把它理解為一個(gè)帶有指針的數(shù)組,我們可以通過(guò)操作“指針”來(lái)獲取其中的數(shù)組。每次我們通過(guò)一定的條件進(jìn)行數(shù)據(jù)庫(kù)查詢(xún)時(shí),返回的就是一個(gè)Cursor, 它可以依次指向查詢(xún)結(jié)果記錄的每一條。不小心又說(shuō)多了,來(lái),寫(xiě)代碼,在NoteLab中創(chuàng)建如下方法:
private Cursor queryNote(String whereClause,String[] whereArgs){ Cursor cursor = database.query( NoteDbScheme.NoteTable.name, null, whereClause, whereArgs, null, null, null ); return cursor }
我們需要關(guān)注的是query方法,第一個(gè)參數(shù)是要查詢(xún)的表名,第三個(gè)參數(shù)和第四個(gè)參數(shù)對(duì)應(yīng)SQL語(yǔ)句中的where(少年,去回顧一下sql語(yǔ)句吧)。
但Cursor還不不太利于我們的操作,來(lái)粉飾一波,在Cursor外面再裹上一層,因此就有了CursorWrapper,創(chuàng)建一個(gè)類(lèi)讓它繼承CursorWrapper:
public class NoteCursorWrapper extends CursorWrapper { public NoteCursorWrapper(Cursor cursor){ super(cursor); } }
變更剛剛的queryNote方法:
private CursorWrapper queryNote(String whereClause, String[] whereArgs){
Cursor cursor = database.query( NoteDbScheme.NoteTable.name, null, whereClause, whereArgs, null, null, null ); return new CursorWrapper(cursor);
}
之所以說(shuō)CursorWrapper方便,是因?yàn)槲覀儗⒉樵?xún)返回的Cursor傳入該類(lèi)之后,可以很方便的把查詢(xún)的值取出來(lái),還是看代碼:
......
......
別看了,太晚了,寫(xiě)之前沒(méi)料到會(huì)有這么長(zhǎng)。明天繼續(xù)寫(xiě)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/65586.html
摘要:業(yè)務(wù)層,業(yè)務(wù)層,是最為核心的一層。對(duì)于和的狀態(tài)保存恢復(fù)也通過(guò)處理。對(duì)于的綁定操作和命令操作都是暴露的,也易于測(cè)試。需要注意的是標(biāo)簽的節(jié)點(diǎn)中要使用到根節(jié)點(diǎn)中標(biāo)簽里設(shè)置的的話(huà)需要這樣設(shè)置抽象類(lèi)中設(shè)置了和注解,只起到清晰提醒作用。 原文發(fā)表于:Rockos blog(rocko.xyz)] - MVVM_Android-CleanArchitecture 前言 Architecture is...
閱讀 3338·2021-09-28 09:36
閱讀 3857·2021-09-08 09:45
閱讀 2041·2021-09-01 10:43
閱讀 3653·2019-08-30 12:44
閱讀 3442·2019-08-29 17:25
閱讀 1461·2019-08-29 11:03
閱讀 2079·2019-08-26 13:36
閱讀 783·2019-08-23 18:24