編輯:關於Android編程
在上一篇博客《打造android ORM框架opendroid(二)——自動創建數據庫》中,我們介紹了opendroid是怎麼做到自動幫我們創建好數據庫並通過反射拼湊出創建數據庫的SQL語句,接著上面的博客,今天要來介紹一下opendroid數據庫持久化(也就是insert操作)是怎麼一個流程。
廢話不多少,我們馬上進入主題。
...
還記得通過opendroid我們是如何將數據保存到數據庫的嗎? 當時是調用了從OpenDroid類繼承過來的save方法,來回顧一下吧。
Student stu = new Student(); stu.setStuName(亓斌); stu.setStuAge(18); stu.save();
按照慣例,我們定位到save()的源碼。
/** * 插入數據 * @return 最後插入的id */ public long save() { try { Classklass = (Class ) getClass(); ContentValues cv = new ContentValues(); generateData(klass, cv); return CRUD.insert(klass.getSimpleName(), cv, sSqliteDatabase); } catch (Exception e) { e.printStackTrace(); } return -1; }
首先第7行,通過getClass方法獲取了當前代表當前對象的Class。
接著第8行new了一個ContentValues,相信大家對它肯定再熟悉不過了。
9行,調用了generateData方法,這個方法有兩個參數,第一個是一個Class對象,第7行的時候我們已經獲取了,第二個參數是一個ContentValues,用來保存存放將要插入數據庫的數據。
接著在11行,調用了CRUD類中的insert靜態方法來保存數據,insert方法的第一個參數是要插入的表名,因為我們的表和bean是一一對應的,所以當前類名就是我們要操作的表名,第二個參數是一個SQLiteDatabase對象。
CRUD.insert方法會返回一個long類型的返回值,相信大家已經猜到了,返回值就是我們新插入數據的id。
分析完這個方法,接下來我們就來看看第9行中調用的generateData方法.
/** * 生成數據 * @param tableName 要獲取的表名 * @param values 要獲取的數據 * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException */ private void generateData(Classklass, ContentValues values) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Field[] fields = klass.getDeclaredFields(); // 獲取類中的所有字段 Method m; String fieldName; String methodName; for (Field field : fields) { // 如果是public,則忽略 if (field.isAccessible()) { continue; } // 獲取字段的類型 Class fieldType = field.getType(); fieldName = field.getName(); // 獲取字段名稱 // 將字段名稱的首字母大寫,准備拼裝getter(getName) methodName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); // 這裡還要判斷一下類型是不是boolean, // 如果是boolean, 就不是getXXX了,而是isXXX if (fieldType == Boolean.class || fieldType == boolean.class) { m = klass.getDeclaredMethod(is + methodName); } else { m = klass.getDeclaredMethod(get + methodName); // 獲取方法 } // 獲取方法的返回值 Object value = m.invoke(this); // 對於一些類型不支持。。 // 未找到解決方案 if (value == null) { // 如果是null,則在contentValues裡添加一個null // values.putNull(fieldName); continue; } // 通過判斷field的類型,向contentValues插入對應的數據 if (fieldType == Integer.class || fieldType == int.class) { values.put(fieldName, Integer.parseInt(m.invoke(this).toString())); } else if (fieldType == Boolean.class || fieldType == boolean.class) { values.put(fieldName, Boolean.parseBoolean(m.invoke(this).toString())); } else { values.put(fieldName, m.invoke(this).toString()); } } }
方法的參數我們在上面已經說明了,這裡就不重復了,在方法剛開始,接連不斷的定義了4個變量,第一個變量是我們通過klass獲取到的該類中所有的字段,接下來我們要通過這些字段來獲取要保存的值和字段名。剩下的幾個變量我們在用到的時候再來說。
17行,進入了一個for循環,遍歷的所有的字段,循環中,19~21行,我們依然去判斷該字段是不是public,如果是public,則證明該字段並沒有映射到數據庫中。
24行,獲取了字段的類型,因為在下面我們要通過類型來設置值。
26~28行,我們准備去拼湊getter方法。
接著32~36行,又是一個判斷,主要是為了我們java bean定義的規范,如果是boolean類型的,我們在定義方法的時候難道不是isXXX嗎?
ok,我們通過反射獲取了將要調用的的方法,接下來39行就要通過getter方法來獲取具體的值了。
42~46行是一個敗筆,還未能結果對於沒考慮到的類型的怎麼去支持,不過也不影響,常用的類型已經支持了。
49~55行,通過字段的類型,來向ContentValues中保存不同類型的值,可以看到我們使用調用m.invoke方法來執行反射出來的方法。
至此,我們已經將數據都保存進ContentValues中了,接下來就是調用android原生的api代碼,將數據庫保存進數據庫就ok了。
而保存進數據庫肯定就是調用了CRUD.insert方法,趕緊來看看這個方法吧。
/** * 插入數據 * @param t 對應的bean * @param db 數據庫操作 * @return 最新插入的id */ protected static long insert(String tableName, ContentValues cv, SQLiteDatabase db) { long id = db.insert(tableName, null, cv); return id; }
好,opendroid的數據持久化流程就說到這裡,在接下來的博客中我們還會去了解opendroid的其他操作。
本文實例分析了Android可循環顯示圖像的Android Gallery組件用法。分享給大家供大家參考,具體如下:Gallery組件主要用於橫向顯示圖像列表,不過按常規
初始化對象private Paint mPaint;//畫筆 private int count;//點擊次數 private Rect rect;//矩形 public
struts2 接收輸入參數的3種方式在我們的生活中,有很多的網頁都存在用戶登陸界面,當我們在登陸界面上輸入自己的用戶名和密碼後,這些數據都會傳入後台,供後台來驗證我們所
滑動導航菜單一直都是移動App中比較流行的UI設計,隨著Material Design的盛行Android也越來越多采用這種設計,當然這種滑動菜單樣式也是各種各樣五花八門