最近在学习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();
}
}
在对Date类型处理逻辑的后面添加 添加对Bitmap类型数据的处理操作。
<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);
}
}
(7)重新编译,导出jar包,下面我们就可以使用我们修改之后的andbase框架存储biamap类型的数据啦。
(8)下面为使用重新编译之后的andbase jar文件插入bitmap数据的例子。
1)定义orm映射对象
2)定义Dao类
3)定义DBInsideHelper类。
4)Activity的实现。
5)好了,运行一下,看一下我们的找事效果: