清风徐来的博客

学的越多,越知道自己的渺小。

利用注解实现BindView、OnClick。

此篇博客记录如何用annotation来实现View的自动绑定,及点击事件的绑定,不同于ButterKnife,本文采用的是Runtime注解,性能相比ButterKnife较低,ButterKnife采用的是编译注解,故性能更高。

BindView

声明注解

以BindView为例,首先需要声明注解

@Retention(AnnotationRetention.RUNTIME) //保存在内存中的字节码,JVM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
@Target(AnnotationTarget.FIELD)//作用于成员变量、对象、属性(包括enum实例)
annotation class BindView(@IdRes val value: Int)

处理注解

object ViewBinder {

    fun bind(activity: Activity) {
        val clazz = activity.javaClass
        val fields = clazz.declaredFields
        fields.forEach {
            //判断注解是否存在
            if (it.isAnnotationPresent(BindView::class.java)) {
                //获取注解
                val viewId = it.getAnnotation(BindView::class.java).value
                val findView = clazz.getMethod("findViewById", Int::class.java)
                val view = findView.invoke(activity, viewId)
                it.isAccessible = true
                //赋值给注解标注的对象
                it.set(activity, view)
            }
        }
    }
}

使用注解

class MainActivity : AppCompatActivity() {
    @BindView(R.id.tv_bind_test)
    lateinit var testTv: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ViewBinder.bind(this)
        testTv.text = "注解成功注入"
    }
}

以上就可以成功完成对于View的绑定

OnClick

声明注解

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class OnClick(@IdRes val value: Int)

处理注解

object ViewBinder {

    fun bind(activity: Activity) {
        val clazz = activity.javaClass
        val fields = clazz.declaredFields
        fields.forEach {
            //判断注解是否存在
            if (it.isAnnotationPresent(BindView::class.java)) {
                //获取注解
                val viewId = it.getAnnotation(BindView::class.java).value
                val findView = clazz.getMethod("findViewById", Int::class.java)
                val view = findView.invoke(activity, viewId)
                it.isAccessible = true
                //赋值给注解标注的对象
                it.set(activity, view)
            }
        }

        val methods = clazz.declaredMethods
        methods.forEach { method ->
            if (method.isAnnotationPresent(OnClick::class.java)) {
                val viewId = method.getAnnotation(OnClick::class.java).value
                val findView = clazz.getMethod("findViewById", Int::class.java)
                val view = findView.invoke(activity, viewId)
                method.isAccessible = true
                (view as View).setOnClickListener {
                    val types = method.genericParameterTypes
                     //判断方法参数长度
                    when (types.size) {
                        0 -> method.invoke(activity)
                        1 -> method.invoke(activity, it)
                    }
                }
            }
        }
    }
}

使用注解

    @OnClick(R.id.btn_click_test)
    private fun onMainTvClick(v: View) {
        Toast.makeText(MainActivity@ this, "click", Toast.LENGTH_SHORT).show()
    }

本篇博客不对注解及反射内容详细记录,后续有时间记得进行一次系统的记录。

阅读更多
版权声明:转载请说明出处 https://blog.csdn.net/xuyonghong1122/article/details/80347201
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

利用注解实现BindView、OnClick。

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭