最近在学习andbase开发框架,该框架实现了许多android开发中常用的功能,为我们针对android应用的开发提供了很大的便利,在使用的过程中,由于项目的需求,需要在APP中存储图片信息,LZ比较懒没有保存文件信息,而是想直接在sqlite数据库中保存Bitmap类型的数据,但是发现这个orm框架不支持这样的操作。于是下载源码,修改一番,终于修改成功。
下面是lz修改源码的整个过程:
(1)在github中下载andbase源码,下载地址:点击打开链接 ,也可以直接在:点击打开链接
(2)将下载的andbase源码导入到eclipse中(lz比较习惯使用),如下图所示,可以看到andbase的源码,其中红框标注的部分为数据库orm框架的实现源码(当然有兴趣的童鞋可以好好研究一下其他部门的源码,写这个框架的作者是一个很厉害的大牛,膜拜)。
(3)在使用andbase的orm框架的时候,我们操作数据库基本都是使用AbDBDaoImpl这个实现类的方法,所以我们找到这个类的源码,在插入和查询方法时,增加对Bitmap类型数据的支持,就应该可以实现我们的目的了,及修改andbase源码增加数据库对bitmap类型数据的支持。
(4)首先查找插入方法的实现,根据对代码的追踪过程中,可以查找到如下代码,其中有一个重要的方法时setContentValues,这个方法是初始化插入sql语句以及ContentValues对象。下面我们查看方法setContentValues方法的实现细节。
/** * 描述:插入实体. * @param entity the entity * @param flag the flag * @return the long * @see com.ab.db.orm.dao.AbDBDao#insert(java.lang.Object, boolean) */ @Override public long insert(T entity, boolean flag) { String sql = null; long row = 0L; try { lock.lock(); ContentValues cv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(entity, cv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(entity, cv, TYPE_NOT_INCREMENT,METHOD_INSERT); } Log.d(TAG, "[insert]: insert into " + this.tableName + " " + sql); Log.d("abc", sql); row = db.insert(this.tableName, null, cv); //获取关联域的操作类型和关系类型 String foreignKey = null; String type = null; String action = null;
(5)查看setContentValues方法的实现细节,我们可以看到其中有对Date类型数据的处理逻辑,所以我们只需要在这其中添加对Bitmap类型的处理,即可实现对Bitmap类型数据的插入操作。
/** * 设置这个ContentValues. * * @param entity 映射实体 * @param cv the cv * @param type id类的类型,是否自增 * @param method 预执行的操作 * @return sql的字符串 * @throws IllegalAccessException the illegal access exception */ private String setContentValues(T entity, ContentValues cv, int type, int method) throws IllegalAccessException { StringBuffer strField = new StringBuffer("("); StringBuffer strValue = new StringBuffer(" values("); StringBuffer strUpdate = new StringBuffer(" "); // 加载所有字段 List<Field> allFields = AbTableHelper.joinFields(entity.getClass().getDeclaredFields(), entity.getClass().getSuperclass().getDeclaredFields()); for (Field field : allFields) { if (!field.isAnnotationPresent(Column.class)) { continue; } Column column = (Column) field.getAnnotation(Column.class); field.setAccessible(true); Object fieldValue = field.get(entity); if (fieldValue == null) continue; if ((type == TYPE_INCREMENT) && (field.isAnnotationPresent(Id.class))) { continue; } // 处理java.util.Date类型,update if (Date.class == field.getType()) { // 2012-06-10 cv.put(column.name(), ((Date) fieldValue).getTime()); continue; } String value = String.valueOf(fieldValue); cv.put(column.name(), value); if (method == METHOD_INSERT) { strField.append(column.name()).append(","); strValue.append("'").append(value).append("',"); } else { strUpdate.append(column.name()).append("=").append("'").append( value).append("',"); } } if (method == METHOD_INSERT) { strField.deleteCharAt(strField.length() - 1).append(")"); strValue.deleteCharAt(strValue.length() - 1).append(")"); return strField.toString() + strValue.toString(); } else { return strUpdate.deleteCharAt(strUpdate.length() - 1).append(" ").toString(); } }
<span style="white-space:pre"> </span>if (Bitmap.class == field.getType()) { Bitmap bitmap = (Bitmap) fieldValue; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); cv.put(column.name(), baos.toByteArray()); continue; }
现在andbase的orm框架的插入操作已经可以支持Bitmap类型的数据了。别高兴的太早,现在我们只是支持对btimap类型数据的插入操作,查询时还是不支持的,下面我们需要修改查询时的源码,使其支持对Bitmap对象的支持。
(6)修改查询方法源码。一般数据查询的时候都是使用的queryList()方法,通过对源代码的追踪我们可以查看到getListFromCursor方法里面含有对反射类型数据的处理逻辑,下面的操作就简单了,添加对bitmap数据的支持就好了(注意53行及以后的处理)。
/** * 从游标中获得映射对象列表. * * @param list 返回的映射对象列表 * @param cursor 当前游标 * @return the list from cursor * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception */ private void getListFromCursor(Class<?> clazz,List<T> list, Cursor cursor) throws IllegalAccessException, InstantiationException { while (cursor.moveToNext()) { Object entity = clazz.newInstance(); // 加载所有字段 List<Field> allFields = AbTableHelper.joinFields(entity.getClass().getDeclaredFields(), entity.getClass().getSuperclass().getDeclaredFields()); for (Field field : allFields) { Column column = null; if (field.isAnnotationPresent(Column.class)) { column = (Column) field.getAnnotation(Column.class); field.setAccessible(true); Class<?> fieldType = field.getType(); int c = cursor.getColumnIndex(column.name()); if (c < 0) { continue; // 如果不存则循环下个属性值 } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) { field.set(entity, cursor.getInt(c)); } else if (String.class == fieldType) { field.set(entity, cursor.getString(c)); } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) { field.set(entity, Long.valueOf(cursor.getLong(c))); } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) { field.set(entity, Float.valueOf(cursor.getFloat(c))); } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) { field.set(entity, Short.valueOf(cursor.getShort(c))); } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) { field.set(entity, Double.valueOf(cursor.getDouble(c))); } else if (Date.class == fieldType) {// 处理java.util.Date类型,update2012-06-10 Date date = new Date(); date.setTime(cursor.getLong(c)); field.set(entity, date); } else if (Blob.class == fieldType) { field.set(entity, cursor.getBlob(c)); } else if (Bitmap.class == fieldType) { byte[] byt = cursor.getBlob(c); field.set(entity, BitmapFactory.decodeByteArray(byt, 0, byt.length)); } else if (Character.TYPE == fieldType) { String fieldValue = cursor.getString(c); if ((fieldValue != null) && (fieldValue.length() > 0)) { field.set(entity, Character.valueOf(fieldValue.charAt(0))); } }else if ((Boolean.TYPE == fieldType) || (Boolean.class == fieldType)) { String temp = cursor.getString(c); if ("true".equals(temp) || "1".equals(temp)){ field.set(entity, true); }else{ field.set(entity, false); } } } } list.add((T) entity); } }
(8)下面为使用重新编译之后的andbase jar文件插入bitmap数据的例子。
1)定义orm映射对象
2)定义Dao类
3)定义DBInsideHelper类。
4)Activity的实现。
5)好了,运行一下,看一下我们的找事效果: