• 开源库ActiveAndroid + gson使用


    ActiceAndroid的简介

    ActiveAndroid是一个活跃的记录风格的ORM(对象关系映射)库。ActiveAndroid可以让您保存和检索的SQLite数据库记录而没有写一个SQL语句。每个数据库记录被整齐包裹成一个model类,像保存方法()和delete()。

    AA使用教材:https://github.com/pardom/ActiveAndroid/wiki/Getting-started

    AA在数据库save,select动作中,只能处理基本数据类型,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,而不是空字符串,是由于构建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

  • 相关阅读:
    Explicitly configure spring.jpa.open-in-view to disable this warning
    [LeetCode] 982. Triples with Bitwise AND Equal To Zero 按位与为零的三元组
    [LeetCode] 981. Time Based Key-Value Store 基于时间的键值存储
    [LeetCode] 980. Unique Paths III 不同的路径之三
    [LeetCode] 979. Distribute Coins in Binary Tree 在二叉树中分配硬币
    [LeetCode] 978. Longest Turbulent Subarray 最长湍流子数组
    [LeetCode] 976. Largest Perimeter Triangle 最大周长的三角形
    [LeetCode] 977. Squares of a Sorted Array 有序数组的平方值
    [LeetCode] 975. Odd Even Jump 奇偶跳跃
    [LeetCode] 974. Subarray Sums Divisible by K 子数组数字之和可被K整除
  • 原文地址:https://www.cnblogs.com/sihaixuan/p/4141084.html
Copyright © 2020-2023  润新知