scanning for model in Activeandroid—TableInfo TypeSerializer

Posted Gjson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scanning for model in Activeandroid—TableInfo TypeSerializer相关的知识,希望对你有一定的参考价值。

  1. TableInfo在构造时会传入一个Class<\\? extends Model> type对象作为参数:

    • 调用type.getAnnotation(Table.class) 得到一个Table注解类,里面描述了该Model对应的DB的table的信息
    • 如果确实得到了一个Table注解对象,那么会将该对象的name/id保存在mTableName/mIdName中.
    • 如果没有得到对应的Table注解对象(即该Model类并没有加table注解), 那么mTableName会取成该Model类的getSimpleName(). 而mIdName则使用一开始的默认值: Table.DEFAULT_ID_NAME = “Id”
    • 调用getIdField(type)得到Model类中标识Id的Field: getIdField(type)的逻辑是: 
      • 如果传入的Class类型是Model.class, 那么返回该Class对象的”mId” Field.
      • 否则如果不是,并且该Class还有父类,那么对此父类调用getIdField(type.getSuperClass())
      • 最终返回的应该是一个对应的name为”mId”的Field.
    • 得到Field对象以后,会将其作为key, mIdName为Value放入到mColumnNames中.
    • 调用ReflectionUtils.getDeclaredColumnFields(type)得到一个Field的列表.

      • ReflectionUtils.getDeclaredColumnFields()的实现: 
        • 只有在传入的type是 Model.class以及其子类时才会对其进行解析.
        • 夺取type的getDeclaredFields(), 然后对得到的Field数组其进行遍历, 如果某个Field isAnnotationPresent(Column.class)即有Column注解. 那么会将此Field加入到返回的结果中.
        • 在处理完此类本身以后,还会对其父类也做同样的处理,最终将该类以及其祖先的所有满足条件的Field对象得到并返回.
    • 回到TableInfo的构造函数, 对返回的具有Column注解的Field对象进行遍历处理, 得到每个Field对象的Column.class注解即一个Column对象. 获取此Column对象的name作为Table的columnName, 如果是空的话,就用Field本身的name作为ColumnName. 将此Field对象和前面得到的columnName放入到mColumnNames中.

    • 从上面分析可见, 对于Id这个特殊的Column, 其columnName是有特殊处理的.
  2. TypeSerializer:

    • 在Configuration的构造过程中调用addTypeSerializer(…)可以加入一个具体的TypeSerializer子类实现对象.
    • 在Configuration的构造中,如果之前填入了有效的TypeSerializer对象,那么Configuration的mTypeSerializers就使用之前填入的TypeSerializer对象.
    • 否则,如果没有添加过有效的TypeSerializer对象, 那么会调用ReflectionUtils.getMetaData(mContext, AA_SERIALIZERS(“AA_SERIALIZERS”))获取一个String, 然后在String不为空的情况下,调用loadSerializerList(serializerList.split(“,”)(字符串之间以“,”分割))得到一批TypeSerializer对象. 
      • loadSerializerList(String[] serializers): 获取当前的classLoader(mContext.getClass().getClassLoader()), 然后使用检测传入的serializers字符串数组, 以字符串内容作为类名,结合Class.forName(serializer.trim(), false, classLoader)获取一个Class对象,并检测该Class对象是否是一个TypeSerializer,如果是的话,就加入到一个list中, 最后返回该list, list中装的都是在AA_SERIALIZERS meta data中指定,并且是TypeSerializer的Class的Class对象.
    • 由上可见,在Configuration构造过程中加入TypeSerializer和在meta-data中指定TypeSerializer, 是互斥的.
    • Configuration中的mTypeSerializers(即TypeSerializer类对象列表), 会在ModelInfo中的loadModelFromMetaData(Configuration configuration)中被使用,并将该List中所有的Class进行实例化instance然后mTypeSerializers.put(instance**.getDeserializedType()**, instance)将其存储在TypeSerializerMap中.
    • TypeSerializer的getDeserializedType()返回的是一个Class 对象,标识了该Serializer可以进行串行化的类型.
    • ModelInfo中保存的mTypeSerializers会通过Cache的getParserForType(Class<\\?> type)调用ModelInfo的getTypeSerializer(type)得到一个针对输入的Type的Class类型的TypeSerializer
    • Cache的getParserForType(..)会在Model的save()和loadFromCursor(…)中被使用,以进行数组的串行化和恢复.
    • TypeSerializer使得调用者可以自行决定自己定义的Model类中的特殊非基本类型成员该如何被序列化已经持久化到DB中, 比如Map/List
  3. Model save()

    • 先调用Cache的openDatabase()得到一个SQLiteDatabase db,并new一个ContentValues用来保存要存储的值.
    • Model的mTableInfo中保存了此Model类中需要进行保存的所有相关的Field.
    • 并根据此Field从mTableInfo中取出对应的columnName.
    • 获取field.get(this)得到此Field
    • 根据Field的Type可以在Cache中通过getParserForType得到相应的TypeSerializer, 如果不是null, 那么说明找到了一个可以用的TypeSerializer.
    • 使用得到的TypeSerializer来对Field的Value的进行serialize(value), 如果serialize以后得到的结果对象不是null, 那么调用其getClass(因为TypeSerializer的serialize()和deserialize()返回的类型都是Object, 而标识其串行和反串行类型的则是由getDeserializedType()/getSerializedType()来标识的), 并检测结果对象的类型是不是TypeSerializer指定的getSerializedType()即在序列化以后的结果的类型. 之前表明Field类型的fieldType也会替换为序列化之后的结果对象的类型.
    • 在经过Serialize以后(如果有对应的TypeSerializer的话), 会根据此时Value的类型将value进行转型并存放到要传给SqlDataBase的ContentValue中.
    • 转型只支持几种类型: null(会调用contentValue的putNull(fieldName))/Byte/byte/Short/short/Integer/int/Long/long/Float/float/Double/double/Boolean/boolean/Character/char/String/Byte[]/byte[]/Model及其衍生类,不过这里实际存的只是Model的Id/Enum,但是实际存的是name(), 对于其他的类型的数据,一概忽略.

以上是关于scanning for model in Activeandroid—TableInfo TypeSerializer的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflowhed-tutorial-for-document-scanning

Tensorflowhed-tutorial-for-document-scanning

while scanning for the next token found character ‘@‘ that cannot start any token

js中的各种遍历(forEach, map, for, for...in, for...of)

流程引擎Camunda开发记录(四)—表 ACT_RE_PROCDEF、ACT_RE_DEPLOYMENT、ACT_RE_MODEL

How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras