文章目录[x]
- 1:Kotlin中的注解
- 2:通过反射和注解来实现IOC注解框架
- 2.1:FindViewById的注入
- 2.2:点击事件的注入
- 3:总结
在系列Android架构中,将持续更新项目中用到的架构和技术,该项目的已发布至github。文中的代码位于com.melrose1994.baselibrary.ioc包下;
Kotlin中的注解
在Kotlin中定义注解非常简单:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
@Repeatable
@MustBeDocumented
annotation class MustRunOnIOThread
其中Retention表示该注解确定是否存储在二进制输出中并且可见而可以进行反射。 默认情况下,两者均为真。分别对应枚举AnnotationRetention下的SOURCE、BINARY、RUNTIME:
- SOURCE:该注解不会存储到编译后的二进制文件中;
- BINARY:该注解会存储到编译后的二进制文件中,但对于反射不可见;
- RUNTIME:该注解会存储到编译后的二进制文件中,对于反射可见;
其中Target表示该注解用来标记的元素,对应枚举AnnotationTarget,常见的如下:
- CLASS:可以用于标记class、object、interface和注解;
- ANNOTATION_CLASS:只能用于标记注解;
- PROPERTY:用于标记属性;
- FIELD:用于标记字段;
- CONSTRUCTOR:用于标记构造函数;
- FUNCTION:用于标记函数(不包含构造函数);
- EXPRESSION:用于标记表达式;
其中Repeatable表示该注解可以多次标记同一个元素;MustBeDocumented表示此注解是公共API的一部分,因此应将其包含在生成的应用注释的元素的文档中。
通过反射和注解来实现IOC注解框架
FindViewById的注入
要通过注解来实现通过ID查找View很简单:
@ViewById(R.id.tvMessage)
private lateinit var mTextView:TextView
首先拿到Activity中的Filed,然后查找是否有ViewById注解,如果有,拿到ID,然后通过ID查找View,然后将查找到的View设置给该Filed:
private fun Activity.injectFiled(){
for (filed in javaClass.declaredFields){
filed.getAnnotation(ViewById::class.java)?.let {
filed.isAccessible = true
filed.set(this,findById(it.idRes,this))
}
}
}
点击事件的注入
要实现如下事件的注入也很简单:
@OnClick(intArrayOf(R.id.tvMessage))
private fun onTextClick(v: View){
Toast.makeText(this,"text click",Toast.LENGTH_SHORT).show()
}
方法的注入的思路为先拿到Activity中的Method,判断该Method是否有注解OnClick,如果有,再根据ID查找View然后设置点击事件来执行该Method;
private fun Activity.injectEvent(){
for (method in javaClass.declaredMethods){
method.getAnnotation(OnClick::class.java)?.let {
method.isAccessible = true
for (viewId in it.idResArr){
val view = findById(viewId,this)
view?.setOnClickListener { method.invoke(this,view) }
}
}
}
}
总结
利用反射加注解来实现的IOC框架在性能上肯定会存在一些缺陷,可以使用ButterKnife的ButterKnifeProcessor生成class的方法来进行优化。