標籤:des android style blog http io ar color 使用
ActiceAndroid的簡介
ActiveAndroid是一個活躍的記錄風格的ORM(對象關係映射)庫。ActiveAndroid可以讓您儲存和檢索的SQLite資料庫記錄而沒有寫一個SQL語句。每個資料庫記錄被整齊包裹成一個model類,像儲存方法()和delete()。
AA使用教材:https://github.com/pardom/ActiveAndroid/wiki/Getting-started。
AA在資料庫save,select動作中,只能處理基礎資料型別 (Elementary Data Type),int,long,String等,對於自訂類型,則需要使用TypeSerializer類型序列化。AAapi中也實現好幾種TypeSerializer。
問題1:AA結合gson使用
Gson gson = new Gson();Log.d("ActiveAndroid","item toJson:"+gson.toJson(obj));//obj繼承com.activeandroid.Model;
會出現報對象序列化異常:
這是由於ActiveAndroid架構需要模型繼承com.activeandroid.Model類,而這個類貌似不能序列化,具體原因未深究,有興趣的同學可以看看ActiveAndroid的源碼。
在ActiveAndroid的Git上查閱了Issue後,發現有開發人員遇到類似問題,但沒有有效解決辦法。
網上解決方案:我們在序列化時忽略父類(com.activeandroid.Model)的屬性,實現com.google.gson.ExclusionStrategy介面策略來構建gson,可以解決這個序列化問題。
public class ActiveAndroidStrategy implements ExclusionStrategy { private Class<?> excludedThisClass; private Class<?> excludedThisClassFields; public ActiveAndroidStrategy(Class<?> excludedThisClass, Class<?> excludedThisClassFields){ this.excludedThisClass = excludedThisClass; this.excludedThisClassFields = excludedThisClassFields; } @Override public boolean shouldSkipField(FieldAttributes f) { return f.getDeclaringClass().equals(excludedThisClassFields); } @Override public boolean shouldSkipClass(Class<?> clazz) { if(clazz == null){ return false; } if(clazz.equals(excludedThisClass)){ return true; } return shouldSkipClass(clazz.getSuperclass()); }}
構建gson
Gson gson = new GsonBuilder().setExclusionStrategies(new ActiveAndroidStrategy(null, Model.class)).serializeNulls().create(); Log.d("ActiveAndroid","item toJson:"+gson.toJson(obj));
問題二
對ActiveAndroid自訂model類型,或者model的集合作為一實體的屬性,沒有使用TypeSerializer,儲存到資料中的值為空白。
舉例:實體item 中含有自訂實體 Category,ChildItem集合
@Table(name ="Items")public class Item extends Model{ @Column(name = "Name") public String name; @Column(name = "Category") public Category category; @Column(name = "ChildItems") public List<ChildItem> childItems; }
從資料庫讀取items中的資料列印:
category,childItems值為空白,注意值為null,而不是Null 字元串,是友構建gson對象,調用serializeNulls()。
解決方案:對於參考型別的欄位,儲存到資料庫中我們習慣儲存為json格式字串,讀取時,把字串轉為相應的參考型別對象,TypeSerializer介面正好完成這樣的工作。
public abstract class Serializer extends TypeSerializer{ protected Gson gson = new GsonBuilder().setExclusionStrategies(new ActiveAndroidStrategy(null, Model.class)).create();
//序列化後的Class類型 @Override public Class<?> getSerializedType() { return String.class; }
//序列化為String @Override public Object serialize(Object data) { if(data == null){ return null; } return gson.toJson(data); }}
//自訂的實體序列化器介面
public class CategorySerializer extends Serializer {
//還原序列化後的類型
public Class<?> getDeserializedType() {
return Category.class;
}
//還原序列化為Category對象
public Object deserialize(Object data) {
if(data == null){
return null;
}
return gson.fromJson((String)data,Category.class);
}
}
//實體集合序列化器
public class ListSerializer extends Serializer{
@Override
public Class<?> getDeserializedType() {
return List.class;
}
@Override
public List deserialize(Object data) {
if(data == null){
return null;
}
return gson.fromJson((String)data,new TypeToken<List<ChildItem>>() {
}.getType());
}
}
在AdnroidMinatest.xml中添加中繼資料TypeSerializer
<meta-data android:name="AA_SERIALIZERS" android:value="com.sihaixuan.practice.test.entity.CategorySerializer
,com.sihaixuan.practice.test.entity.ListSerializer"/>
從資料庫中讀取items,測試結果如下:
可以看到category,和childItems都值了。
使用AA小小的抱怨:
1.AA中絕大數類都是final,開放的介面少,可定製性低,比如我想動態添加TypeSerializer,就不行了,暴力點,只能通過反射實現了。
2.假如實體很多時,或者使用的實體集合類型很多時,TypeSerializer類會不會膨脹了,有什麼好的方法避免了。
測試demo:http://pan.baidu.com/s/1dDepZwt
開源庫ActiveAndroid + gson使用