ActiveAndroid 源码阅读笔记 (2)

134 篇文章 0 订阅
79 篇文章 0 订阅
5.TableInfo:
  (1)内部引用: 一个Type, 该Type限制了Class必须extends Model,
    Table名称,Id名称, 一个Field<反射的类型>对象和String的HashMap<存储的就是DB中的ColumnName和内存中
    对象的Field的对应关系>.

  (2)构造函数接受一个Class type(必须extends Model),
    尝试获取此Class type的 Annotation<因为只可能是Table.class>,
    因此会直接传入Table.class, 如果确实获取了,那么就将Table名称和Id名称
    从该Annotation的配置参数中抽出来<这就体现了Table Annotation的作用>。
    如果没有,那么默认Model的className就是Table的Name<要我说可以搞成强制的>。
    再尝试获取Id对应的Field,将此Field和Id的名称(String)存到hashMap中。
    然后得到此Model类中所有的Field,也存在一个List中,
    遍历这些Field,对于有Column Annotation的Field,获取在Annotation中的Name(DB中的
    columnname)然后将此Field和Annotation中的ColumnName存储到hashMap中。
    基本可见,此HashMap存储的就是DB中的ColumnName和内存中对象的Field的对应关系。
   
   (3)一堆的getter返回各种Table的相关信息以及HasMap的Key/valueSet.
   
   (4)getIdField,输入的一个一个Class type, 如果该Class就是Model.class, 那么
    就直接返回Class.getDeclaredField("mId")<这个必有,Model Class声明的>,不过为了
    维稳,还是catch了NoSuchFieldException一下。
    如果不是Model.class, 那么如果该Class 还有 父类,那么就尝试递归调用到其父类type上,
    之外的所有case,都返回null.
   
    现在看来,TableInfo的定位已经很清晰了,就是根据输入的Class Type,来根据自己定义的Table
    Column Annotation进行解析和DB有关的Field以及Name,并存储解析结果到一个hashmap中。
    TableInfo有一部分tool函数功能,也承担了M<中间的>的工作,因此必然会有多个TableInfo对象,
    并且从函数可以看出,只有在构造是才对输入的Class Type进行解析,因此TableInfo对象 和 Model衍生类
    其实是一一对应的,ModelInfo就保存了这个对应关系。

6.ModelInfo:
    (1)ModelInfo其实完全可以作为一个single存在(只有Cache会new它),code也确实是按照single用的,
    只不过作者懒,没有规范模式罢了。
    (2)内部保存了刚才说的Model ClassType 和  TableInfo对应的tableInfos Map.
       以及一个Class Type和 TypeSerializer的对应的Map.(难得一见的匿名类通过初始化块来初始化)
    (3)ModelInfo的初始化参数也是和ActiveAndroid的初始化参数一样(后者传给前者的),
       是自定义的Configuration类。先尝试从MetaData中读取Model信息<如果失败,会尝试scanForModel>,
       首先尝试检测一次Configuration的valid, 然后从configuration中获取一个
       Model衍生类的List表,保存的都是Class type, 同样的也会尝试从configuration中获取一个
       TypeSerializer的List, 如果提供了,那么会根据这些TypeSerializer的DeserializedType将其
       填充到ModelInfo的TypeSerializer的Map中,方便后面查找使用。
    (4)scanForModel()函数就是在Configuration没有传递足够的信息,及load失败的情况下,会被调用来
      扫描一遍源文件<啊哈,预处理在这里>,context.getApplicationInfo().sourceDir可以获取App的源文件路径
      ,必然是dex文件,用此path构造一个DexFile对象(我还真没用过这个),获取dexfile的entry, 并将这些entry
      保存下来,这些是建立在sourceDir不为空或者不是dir的前提下,否则,就会获取当前Thread的classloader,
      Thread.currentThread().getContextClassLoader();(还是真没用过),以classLoader.getResources("")获取
      一堆的URL,如果里面某个URL包含了bin/classes,就会加入到path列表中以后面进行搜索。
      最后遍历上面得到的path, 根据path构建File, 调用scanForModelClasses()<输入了File, packageName以及classLoader>。
    (5)scanForModelClasses()紧接上面,如果File是一个Dir,递归对其成员进行调用。
      对于单个文件,检查path是否是.class文件,.....(先掠过这些),得到一个className,在得到了ClassName以后,
      就可以利用Class.forName()得到Class对象,的到了对象,就可以将其作为参数生成TableInfo并填入到上面的Map中了,
      TypeSerializer同理。(果然需要标注的生命期是RunTime, 不过压根没的查)
     
    scanModel这一步已经比较接近与JVM虚拟机的中级应用了,当然了,
    任何依赖标注进行RunTime操作的可能都会走到这一步,mark一下,以后研究。 这一步在进行proguard混淆出错时会比较
    有用。当然了,也可以让你知道为什么activeAndroid在Proguard.cfg要加新内容.

7.Application:
    没啥说的,就是替懒人小封装了一下罢了,从ActiveAndroid.initialize(this)/dispose()的调用位置(onCreate/onTerminated)
    可以看到,activeAndroid初始化一次的使用期是延续整个App生命期的。    
       
8.Configuration:
   Configuration本身没啥可读的,就是一群信息的封装罢了,参考参考它的builder模式就可以了。从create读取meta-data来得到
   DBName/DBVersion/sqlParser/Model/TypeSerializer可以看到,其实Mainfest.xml的meta-data可以写很多的,不过,有scan在,
   我才懒得加,哈哈.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值