最近学习了一下反射和注解的相关知识点,然后利用该知识点写了两个小功能
- 根据反射的原理来实现了一个把
json数据
转成实体类
- 利用注解实现activity中的FindViewById的功能
关于Java反射的一些知识点可以看一下 Java反射里的常用的方法 这篇文章
还有关于注解的知识点我就不再多说了,百度一下就有很多
功能1 的思路
- 把json字符串和实体类的Class对象给传进来
- 把json字符串转成JSONObject对象
- 根据class对象获取其无参数的构造器,并调用newInstance方法方法来生成实体类对象
- 根据class对象获取其所有参数
- 遍历所有参数并调用参数set方法把从jsonObject中取出的值set进去
功能1 的具体代码
- 方法
fun <T> json2Bean(json: String, c: Class<T>): T? {
val jb: JSONObject = try {
JSONObject(json)
} catch (e: JSONException) {
return null
}
// 首先根据Class对象 获取到实体类的无参构造器
val t: T = c.let {
val const = it.getDeclaredConstructor()
// 这里需要关闭检查
const.isAccessible = true
const.newInstance()
}
val declaredFields = c.declaredFields
// 然后再根据class对象获取到它的参数
if (declaredFields.isNotEmpty()) {
declaredFields.forEach {
it.isAccessible = true
val value: Any? = try {
jb.get(it.name)
} catch (e: JSONException) {
null
}
if (value != null)
it.set(t, value)
}
}
return t
}
- 实体类
data class User(
val id: Int = -1,
val name: String = "",
val age: Int = 0,
) {
override fun toString(): String {
return "User [ id:${id}, name:$name, age:$age ]"
}
}
- 具体使用
private val json1 = """{"name1": "张三", "age1": 23, "id": 2}"""
override fun onCreate(savedInstanceState: Bundle?) {
...
bind.btnGet.setOnClickListener {
val user: User? = Utils.json2Bean(json1, User::class.java)
Log.e("aaa", "user:${user}")
}
}
功能2 的思路
- 根据反射获取activity中所有的字段
- 遍历所有的字段并判断哪些字段设置了注解
- 根据字段获取其注解的值
- 把值设置给该字段
功能2 的具体代码
- 注解类
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class FindView(@IdRes val value: Int = -1)
- 实现类
fun Activity.initAnnotation() {
// 拿到activity的class对象
val clz = this::class.java
// 获取到该class对象的所有字段
val fields = clz.declaredFields
// 遍历所有的字段
fields.forEach {
// 设置不安全检查
it.isAccessible = true
if (it.isAnnotationPresent(FindView::class.java)) {
// 获取到设置有该注解的字段
val findView = it.getAnnotation(FindView::class.java)
// 把注解中的值取出来并调用findViewById的方法
it.set(this, findViewById(findView.value))
}
}
}
- 具体使用
@SuppressLint("NonConstantResourceId", "SetTextI18n")
class DemoActivity : AppCompatActivity() {
@FindView(R.id.btn_test)
private lateinit var btnTest: Button
@FindView(R.id.tv_test)
private lateinit var tvTest: TextView
@FindView(R.id.iv_test)
private lateinit var ivTest: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_demo)
initAnnotation()
}
}