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(), 對於其他的類型的數據,一概忽略.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章