Android-自定义注解-事件注解Type2

作者: MonkeyLei | 来源:发表于2019-07-10 10:22 被阅读0次

基于上一篇Type1,我们现在第二种注解类型,主要还是用法上更趋向butterknife.

@OnClicks(R.id.testSB)
    public void fucnSbs(View view){
        sb.setText("fuck sb 3");
    }

     1.定义OnClicks.java

package com.example.mylibrary;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Author:hl
 * Time:  2018/5/25 10:27
 * Des:   This is OnClick
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClicks {
    int value();                    ///< 控件id
}

2.实现注解翻译,主要是Method的获取和使用

ButterKnife.java

///< 1\. 获取Method方法数组
        Method[] methods = classObj.getDeclaredMethods();
        for (final Method method : methods){
            ///< 2\. 判断是否添加了OnClicks注解
            if (method.isAnnotationPresent(OnClicks.class)){
                ///< 3.获取注解实例对象
                final OnClicks onClicks = method.getAnnotation(OnClicks.class);
                int viewId = onClicks.value();

                try {
                    ///< 4\. 获取控件
                    Method methodFd = classObj.getMethod("findViewById", int.class);
                    final View viewObj = (View)methodFd.invoke(context, viewId);

                    ///< 5.设置点击事件,执行方法
                    viewObj.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            try {
                                method.invoke(context, viewObj);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

3.多个参数版本来一个吧

3.1 修改下OnClicks.java

package com.example.mylibrary;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Author:hl
 * Time:  2018/5/25 10:27
 * Des:   This is OnClick
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClicks {
    int[] value();                    ///< 控件id
}

3.2 优化下ButterKnife.java

///< 1\. 获取Method方法数组 - OnClicks
        Method[] methods = classObj.getDeclaredMethods();
        for (final Method method : methods){
            ///< 2\. 判断是否添加了OnClicks注解
            if (method.isAnnotationPresent(OnClicks.class)){
                ///< 3.获取注解实例对象
                final OnClicks onClicks = method.getAnnotation(OnClicks.class);
                int[] viewId = onClicks.value();

                for (int vId : viewId){
                    try {
                        ///< 4\. 获取控件
                        Method methodFd = classObj.getMethod("findViewById", int.class);
                        final View viewObj = (View)methodFd.invoke(context, vId);

                        ///< 5.设置点击事件,执行方法
                        viewObj.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                try {
                                    method.invoke(context, viewObj);
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                } catch (InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

3.3 使用一下MainActivity.java

@OnClicks({R.id.testSB, R.id.testSB2})
    public void fucnSbs(View view){
        sb.setText("fuck sb 3");
    }

3.4 记得增加一个控件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/testSB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/testSB2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.758" />

</android.support.constraint.ConstraintLayout>

3.4.1 搞定! 这里我把布局粘贴出来了?想提前强调下app:layout_constraintVertical_bias这个属性,这就是约束布局的魅力。真正了解了约束布局,相信可以把布局做得更简化!目前正在利用约束布局重构现有项目,后面分享一下!

image

总结一下,其实和上一篇没太多变化,无外乎就是我们提前获取到了点击事件的Method,进而去执行,其他逻辑还是一样。下面我们尝试把下面这一段做封装,利用到动态代理的方式去改造一下! So,下一步研究动态代理...

.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            try {
                                method.invoke(context, viewObj);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });

相关文章

网友评论

    本文标题:Android-自定义注解-事件注解Type2

    本文链接:https://www.haomeiwen.com/subject/rksckctx.html