編輯:關於Android編程
概述 悠悠綠水傍林侵日落觀山四望回 幽林古寺孤明月冷井寒泉碧映台 鷗飛滿浦漁舟泛鶴伴閒亭仙客來 游徑踏花煙上走流溪遠棹一篷開
一個不小心都寫了三篇了,也不知道大家還看得懂不?如果看不懂最好給我留個言,我好下一次改正。
接著上次的說,准備工作都已經做好了,現在咱們就要開始著手解決阻擋Android數據庫操作通用化的五個問題了。
我們先回顧一下問題: 問題1:表名的獲取 問題2:如何將實體中的數據,按照對應關系導入到數據庫中 問題3:明確實體中主鍵是誰?獲取到主鍵中封裝的值 問題4:如何將數據庫中表的列的數據,按照對應關系,封裝到實體中 問題5:實體的對象創建問題當然是一個一個解決,這樣才有效率,那麼第一個問題來了:表名如何獲取。
通常情況下,解決一個問題時,都會以一個方法或者函數開始,這次也不例外,我們先給一個殼子:
/** 問題一:表名的獲取 **/
public String getTableName() {
return null;
}
一切充滿了希望,也顯得那麼自然。現在我們就要開始思考一些關於如何獲取表名的問題了。
在實際開發中,每一個數據庫表,都會對應著一個具體的實體。就好像news
表對應著News
類。看看它們,是不是名字好相似?只不過一個是首字母大寫,另一個是全小寫。於是我們心底這麼想,如果我們能夠通過“實體”拿到表名就好了。
既然有了路走走看,就知道走的通還是走不通了。
我們可以提出兩個方案: ① 如果能夠獲取到實體,那麼我們就能夠獲取到實體的簡單名稱,然後只需要將首字母小寫就是表名了。但是,這樣的缺點也很明顯,這要求數據庫定義表的名稱和實體的名稱基本一致,這樣就會導致我們定義的實體名稱收到限制。例如:定義了news
表,那麼對應的實體就只能是News
了。 ② 利用注解,這樣就可以讓實體的名稱和數據庫表的名稱之間的關系脫離,兩者互不干涉。缺點也是顯而易見,編碼難度增加,(嘿嘿),不過誰叫咱們是有經驗的開發人員,就選這種了。
如果有同學注解遺忘掉了,或者還不是很清晰,可以參看我的這篇文章:www.2cto.com
明確了道路,一路向前就可以了。
接下來就要使用到注解和反射什麼的了!!是不是有點小激動~哈哈~
接下來的任務,就是給News
實體類增加一個注解了,增加注解的目的則是,將數據庫表和對應實體之間的關系確定下來。請看代碼:
// 注解的作用:將數據庫表和對應的實體確定下來。
@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {
private int id;
private String title;
private String summary;
}
看起來像模像樣的,但是@TableName(DBHelper.TABLE_NEWS_NAME)
這句是什麼? 誰能告訴我?
這句就是我們寫的注解了,但是,此時我們還沒有創建出來,但是不要緊,如果你使用的是Eclipse,請選中這行Ctrl+1
,就可以自動創建了,這麼高大上,是不是被震到了!↖(^ω^)↗。請看具體的TableName
代碼:
/**
* 制定了實體和數據庫中表的對應關系
*/
@Target(ElementType.TYPE) // 指定放置的位置
@Retention(RetentionPolicy.RUNTIME) // 指定存活時間
public @interface TableName {
/**
* 數據庫中的表名,此處可以存放值
*/
String value();
}
一切都是這麼簡單明了,讓人心曠神怡。現在,注解已經創建好,實體上的注解也已經添加完畢,並且傳入了表名。接下來在getTableName
方法中,繼續填寫代碼就好了。
在偽代碼的第一步是獲取到對象的實體,經過查看,這個恰好是第五個問題,我們先放著,寫一個空方法來代表。
/**
* 問題五:實體對象的創建
*/
private M getInstance() {
return null;
}
具體的getTableName()
方法代碼如下所示:
public String getTableName() {
// 偽代碼:
// ① 問題五:獲取到對象的實體
M m = getInstance();
// ② 獲取實體頭上的注解,依據value的設置值,確定操作的數據庫表
// 需要注意的,想要在“運行時”獲取到注解的信息,給注解設置存活時間。
TableName tableName = m.getClass().getAnnotation(TableName.class); // annotationType 注解的類型
// 為了安全起見,判斷注解的合法性;合法則返回value值
if (tableName != null) {
return tableName.value();
}
return null;
}
有了這個方法,BaseDaoSupport
中的delete
方法也就可以寫出來了,依舊很簡單,請看代碼:
@Override
public int delete(Serializable id) {
return db.delete(getTableName(), DBHelper.TABLE_ID + =?, new String[] { id.toString() });
}
小結:其實呢,在表名的獲取中,我們就是利用注解去解決了一個事,表和實體是一一對應的,它們之間的對應關系是什麼。(TableName)
是時候表演真正的技術了!!(╰_╯)#
接下來該解決第二個問題了,如何將實體中的數據,按照對應關系導入到數據庫中。
回想一下第一個問題的解決,其實就是利用注解解決了,表和實體之間的對應關系。以此類推,第二個問題也是要求將實體中的數據,按照對應關系導入到數據庫中。一樣的思路,繼續往下延續,可以再為實體的字段一個注解,來體現和數據庫表中列的對應關系。請看代碼:
/**
* 制定了實體的子對岸和數據庫表中列的對應關系
*/
@Target(ElementType.FIELD) // 指定放置的位置
@Retention(RetentionPolicy.RUNTIME) // 指定存活時間
public @interface Column {
String value();
}
只要字段上有這個注解的,肯定是和數據庫表中的列有對應關系,接下來為實體的字段添加相應的注解,並傳入列名。請看代碼:
// 注解的作用:將數據庫表和對應的實體確定下來。
@TableName(DBHelper.TABLE_NEWS_NAME)
public class News {
// 指定了實體和數據庫中表的對應關系
@Column(DBHelper.TABLE_ID)
private int id;
@Column(DBHelper.TABLE_NEWS_TITLE)
private String title;
@Column(DBHelper.TABLE_NEWS_SUMMARY)
private String summary;
}
准備工作已經做好了,接下來就要填寫insert
中的代碼了,此處新建了一個fillColumn(M m, ContentValues values)
方法,把實體M字段值和字段上Column(XXX)
注解中傳入的列名,用values.put(key,value)
方法填入到valeus中,以便insert
中填寫數據。代碼如下:
@Override
public long insert(M m) {
ContentValues values = new ContentValues();
// m代表數據源,vlaues是數據導入的目標
fillColumn(m, values);
return db.insert(getTableName(), null, values);
}
代碼很簡單,關鍵在於fillColumn(m, values);
的數據填充。通過使用反射技術,獲取到M
實例的所有字段集合,再依次拿到每個字段的值和每個字段注解的值,並填充到values
中,請看代碼:
/**
* 問題二:如何將實體中的數據,按照對應關系導入到數據庫中
*
* @param m 數據源
* @param values 是數據導入的目標
*/
public void fillColumn(M m, ContentValues values) {
// 獲取m上所有的字段
Field[] fields = m.getClass().getDeclaredFields();
for (Field field : fields) {
// 設置訪問權限
field.setAccessible(true);
// 獲取字段頭上的注解
Column column = field.getAnnotation(Column.class);
if (column != null) {
try {
String key = column.value(); // 獲取注解中,指定的列名
String value = field.get(m).toString(); // 獲取字段值
// 填寫數據
values.put(key, value);
} catch (IllegalArgumentException e) {
throw new RuntimeException(字段不屬於m實例);
} catch (IllegalAccessException e) {
throw new RuntimeException(沒有訪問字段域的權限);
}
}
}
}
總結:只要掌握了思路和方法,整潔、清晰的代碼,寫起來也不是那麼困難。
人生不相見,動如參與商.
今夕復何夕,共此燈燭光.
少壯能幾時,鬓發各已蒼.
訪舊半為鬼,驚呼熱中腸.
焉知二十載,重上君子堂.
昔別君未婚,兒女忽成行……
大家在網上購物時都有這樣一個體驗,在確認訂單選擇收貨人以及地址時,會跳轉頁面到我們存入網站內的所有收貨信息(包含收貨地址,收貨人)的界面供我們選擇,一旦我們點擊其中某一條
1、android支持庫未安裝 編譯不過,提示如下: Could not find any version that matches com.android.suppor
基本介紹現在的一些購物類App例如淘寶,京東等,在物品詳情頁,都采用了類似分層的模式,即上拉加載詳情的方式,節省了空間,使用戶的體驗更加的舒適。只要對於某個東西的介紹很多
前幾天一同學項目中的某個功能需要ListView+EditText來實現,希望我給他寫個Demo,自己就隨手寫了一個小的Demo。後來想了想覺得這個功能其實挺常用的,而且