Android——教你10分钟手敲 Butter Knife(小刀注解)

教你10分钟手敲 Butter Knife(小刀注解)

 

在用 AndroidStudio 集成 Butter Knife(小刀注解)的时候感觉像极了J2EE的Spring IOC容器 自己研究了一下,我来分享一下,小编会:多注释,多贴码,尽量降低同学们的学习时间成本,希望喜欢 花里胡哨 的同学不容错过。(求关注(✪ω✪))

简单介绍Butter Knife(小刀注解)是什么鬼:

原生的获取组件是这样的:

public class MainActivity extends AppCompatActivity {

    //定义组件
    private TextView main_tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        main_tv = findViewById(R.id.main_tv);//获取组件

        main_tv.setText("卡哇伊");//使用组件

    }
}

使用 Butter Knife(小刀注解)后的获取组件是这样子的:

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.main_tv)  
    private TextView main_tv;//定义组件

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);   //绑定activity
        main_tv.setText("卡哇伊");//使用组件

    }
    
}

在实际项目中有什么好处呢?

Butter Knife(小刀注解) 优点:

1、强大的View绑定和Click事件处理功能,简化代码,提升开发效率

2、方便的处理Adapter里的ViewHolder绑定问题

3、运行时不会影响APP效率,使用配置方便

4、代码清晰,可读性强

利用插件一键生成,爽到嗨。省去了 findViewById 。不就是利用注解赋值嘛,来小编带你10分钟搞定。

第一步:新建一共空的工程,并新建必要的文件目录 annotation、entity、fragment、util

第二步:在  新建一个注解 取名为 GT_View 并添加相应代码:

GT_View 注解代码:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_View {
    int value();
}

第三步:新建一个 GT_Util.java 的Java文件:

GT_Util 代码:(直接复制粘贴,代码有注释,Java基础好点的看懂的快些)

public class GT_Util {

    /**
     * 注入所有注解
     * @param activity
     */
    public static void initAll(Activity activity){

        initView(activity);                 //为加载 组件 初始化

    }

    /**
     *注入控件
     * @param activity
     */
    private static void initView(Activity activity){
        Class<? extends Activity> clazz = activity.getClass();                              //获取该类信息
        Field[] fields = clazz.getDeclaredFields();                                         //获致所有成员变更
        for (Field field:fields) {                                                          //遍历所有当前 Activity 的成员变量
            GT_View initView = field.getAnnotation(GT_View.class);                          //获取当前变量的 GT_View 注解
            if(initView != null){                                                           //如果为 null 则表明当前成员变量没有被 GT_View 注解标注
                int viewId = initView.value();                                              //获取当前注解上标注的 组件ID
                try {
                    Method method = clazz.getMethod("findViewById", int.class);     //获取当前Activity中 findViewById 方法
                    method.setAccessible(true);                                             //设置 findViewById 方法的 访问权限
                    field.setAccessible(true);                                              //设置 当前成员变量的 访问权限
                    Object object = method.invoke(activity, viewId);                        //注入数据:将ID 注入到 findViewById 中 并返回 View
                    field.set(activity,object);                                             //将返回的 View 设置到 Activity 中
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

第四步:修改xml文件,并在Activity添加相应代码:

activity_main.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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/main_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java 文件:

public class MainActivity extends AppCompatActivity {

    @GT_View(R.id.main_tv)
    private TextView main_tv;   //定义组件

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GT_Util.initAll(this);           //绑定Activity
        main_tv.setText("卡哇伊");       //使用组件
    }

}

运行效果图:

总结:简单吧,10分钟做到这里差不多了,感谢你的阅读。٩(๑>◡<๑)۶ 

如果你并不满足于此,请继续阅读下面。

关注博主最新发布库:GitHub - 1079374315/GT

如果你并不满足于此,不如再花10分钟来搞定这些? 求关注(◕ᴗ◕✿)

@GT_Activity(R.layout.activity_main)//省去了 setContentView 方法
public class MainActivity extends AppCompatActivity {

    @GT_View(R.id.ioc_tv)
    private TextView tv;//获取View组件

    @GT_Object(valueString = "1079",valueInt = 21,types = {GT_Object.TYPE.STRING, GT_Object.TYPE.INT}, functions = {"setUsername","setAge"})
    private LoginBean loginBean;//获取带参数的实体类

    @GT_Res.GT_String(R.string.StringTest)
    private String data;//注入 res下string 字符串资源

    @GT_Res.GT_Color(R.color.colorTest)
    private int MyColor;//注入 res下color 颜色资源

    @GT_Res.GT_Drawable(R.drawable.ic_launcher_background)
    private Drawable btnBG;//注入 res下drawable 图片资源

    @GT_Res.GT_Dimen(R.dimen.tv_size)
    private float TextSize;//注入 res下dimen 尺寸资源

    @GT_Res.GT_Animation(R.anim.alpha)
    private Animation animation;//注入 res下anim 动画资源 

    @GT_Res.GT_StringArray(R.array.ctype)
    private String[] strArray;//注入 res下array string数组资源 

    @GT_Res.GT_IntArray(R.array.textInt)
    private int[] intArray;//注入 res下array int数组资源 

    @GT_Res.GT_Layout(R.layout.activity_main)
    private View layout;//注入 res下array 布局资源 

    @Collection.List({Fragment_1.class,Fragment_2.class,Fragment_3.class})
    List<Object> fragmentList;//实例化3个Fragment并注入到List中

    @Collection.Map({Fragment_1.class,Fragment_2.class,Fragment_3.class})
    Map<Object,Object> fragmentMap;//实例化3个Fragment并注入到Map中

    @Collection.Set({Fragment_1.class,Fragment_2.class,Fragment_3.class})
    Set<Object> fragmentSet;//实例化3个Fragment并注入到Set中

    @GT_Click({R.id.ioc_btn01,R.id.ioc_btn02,R.id.ioc_btn03})
    public void testBtnOnCLick(View view){//监听多按钮单击事件
    

既然你往下滑,那说明我们都是 好奇心 强的人,说好10分钟,我们时间紧迫赶紧的。(๑╹◡╹)ノ"""

第一步:添加必要的注解类 : 

Collection、GT_Activity、GT_Click、GT_Object、GT_Res、GT_View、OnClickEvent

Collection:注解代码如下

/**
 * 集合注解
 */
public @interface Collection {

    /**
     * List 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface List {
        Class[] value();
    }


    /**
     * Map 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Map {
        Class[] value();
    }


    /**
     * Set 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Set {
        Class[] value();
    }

}

GT_Activity:注解代码如下

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_Activity {
    int value();
}

GT_Click:注解代码如下

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@OnClickEvent(listenerType = View.OnClickListener.class,listenerSetter = "setOnClickListener",methodName = "onClick")
public @interface GT_Click {
    int[] value();
}

GT_Object:注解代码如下

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GT_Object {

    interface TYPE {
        String BYTE = "byte";
        String SHORT = "short";
        String INT = "int";
        String LONG = "long";
        String FLOAT = "float";
        String DOUBLE = "double";
        String BOOLEAN = "boolean";
        String CHAR = "char";
        String STRING = "String";

        String BYTES = "bytes";
        String SHORTS = "shorts";
        String INTS = "ints";
        String LONGS = "longs";
        String FLOATS = "floats";
        String DOUBLES = "doubles";
        String BOOLEANS = "booleans";
        String CHARS = "chars";
        String STRINGS = "Strings";
    }

    /** 单参数的传递 **/
    byte        valueByte()     default 0;
    short       valueShort()    default 0;
    int         valueInt()      default 0;
    long        valueLong()     default 0L;
    float       valueFloat()    default 0.0f;
    double      valueDouble()   default 0.0d;
    boolean     valueBoolean()  default false;
    char        valueChar()     default 0;
    String      valueString()   default "";

    /** 多参数的传递 **/
    byte[]      valueBytes()     default {};
    short[]     valueShorts()    default {};
    int[]       valueInts()      default {};
    long[]      valueLongs()     default {};
    float[]     valueFloats()    default {};
    double[]    valueDoubles()   default {};
    boolean[]   valueBooleans()  default {};
    char[]      valueChars()     default {};
    String[]    valueStrings()   default {};

    /** 修改参数的类型 **/
    String      type()           default "";
    String[]    types()          default {};

    /** 要赋值的方法 **/
    String      function()       default "";
    String[]    functions()      default {};

}

GT_Res:注解代码如下

/**
 * 资源注解
 */
public @interface GT_Res {

    /**
     * 字符串 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_String {
        int value();
    }

    /**
     * 颜色 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_Color {
        int value();
    }

    /**
     * 尺寸 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_Dimen {
        int value();
    }

    /**
     * 图片 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_Drawable {
        int value();
    }

    /**
     * 动画 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_Animation {
        int value();
    }

    /**
     * 字符串数组 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_StringArray {
        int value();
    }

    /**
     * 整数数组 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_IntArray {
        int value();
    }

    /**
     * 将 xml 文件解析成 View 注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface GT_Layout {
        int value();
    }

}

OnClickEvent:注解代码如下

@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClickEvent {
    Class<?> listenerType();//接口类型
    String listenerSetter();//设置的方法
    String methodName();//接口里面要实现的方法
}

第二步:更新 GT_Util.java 文件

注意:代码有点多(接近千行),但原理都与上面详细讲解的差异不多所以就直接贴码了。

public class GT_Util {

    //Fragment 注入
    public static void initAll(Object object, View view){

        initView(object,view);                 //为加载 组件 初始化
        initClick(object,view);                //为加载 组件单击 初始化

        initObject(object);                    //为加载 Object 成员变量初始化
        initList(object);                      //为加载 List 成员变量初始化
        initMap(object);                       //为加载 Map 成员变量初始化
        initSet(object);                       //为加载 Set 成员变量初始化

        initAnimation(object,view);            //为加载 Animation 资源初始化
        initDimen(object,view);                //为加载 Dimen 资源初始化
        initDrawable(object,view);             //为加载 Style 资源初始化
        initColor(object,view);                //为加载 Color 资源初始化
        initString(object,view);               //为加载 String 资源初始化
        initIntArray(object,view);             //为加载 IntArray 资源初始化
        initStringArray(object,view);          //为加载 StringArray 资源初始化
        initLayout(object,view);               //为加载 Layout 资源初始化

    }

    /**
     * Fragment 中的使用
     */

    /** Fragment 注入控件*/
    private static void initView(Object object,View view){
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields = clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_View initView = field.getAnnotation(GT_View.class);
            if(initView != null){
                int viewId = initView.value();
                try {
                    View viewById = view.findViewById(viewId);
                    field.setAccessible(true);
                    field.set(object,viewById);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入点击事件 */
    private static void initClick(Object object,View view){
        Class<? extends Object> clazz = object.getClass();
        Method[] methods= clazz.getMethods();//获取所有声明为公有的方法
        for (Method method:methods){//遍历所有公有方法
            Annotation[] annotations = method.getAnnotations();//获取该公有方法的所有注解
            for (Annotation annotation:annotations){//遍历所有注解
                Class<? extends Annotation> annotationType = annotation.annotationType();//获取具体的注解类
                OnClickEvent onClickEvent = annotationType.getAnnotation(OnClickEvent.class);//取出注解的onClickEvent注解
                if(onClickEvent!=null){//如果不为空
                    try {
                        Method valueMethod=annotationType.getDeclaredMethod("value");//获取注解InjectOnClick的value方法
                        int[] viewIds= (int[]) valueMethod.invoke(annotation, (Object[]) null);//获取控件值
                        Class<?> listenerType = onClickEvent.listenerType();//获取接口类型
                        String listenerSetter = onClickEvent.listenerSetter();//获取set方法
                        String methodName = onClickEvent.methodName();//获取接口需要实现的方法
                        MyInvocationHandler handler = new MyInvocationHandler(object);//自己实现的代码,负责调用
                        handler.setMethodMap(methodName,method);//设置方法及设置方法
                        Object object2 = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},handler);//创建动态代理对象类
                        for (int viewId:viewIds){//遍历要设置监听的控件
                            View view2 = view.findViewById(viewId);//获取该控件
                            Method m = view2.getClass().getMethod(listenerSetter, listenerType);//获取方法
                            m.invoke(view2,object2);//调用方法
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /** 注入 Animation 资源字符串 **/
    private static void initAnimation(Object object, View view) {
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Animation initView = field.getAnnotation(GT_Res.GT_Animation.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    Context context = view.getContext();
                    if(context != null){
                        Animation animation = AnimationUtils.loadAnimation(context, viewRes);
                        field.setAccessible(true);
                        field.set(object,animation);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Dimen 资源字符串 **/
    private static void initDimen(Object object, View view) {
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Dimen initView = field.getAnnotation(GT_Res.GT_Dimen.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    float dimension = view.getResources().getDimension(viewRes);
                    field.setAccessible(true);
                    field.set(object,dimension);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Drawable 资源字符串 **/
    private static void initDrawable(Object object, View view) {
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Drawable initView = field.getAnnotation(GT_Res.GT_Drawable.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    Drawable drawable = view.getResources().getDrawable(viewRes);
                    field.setAccessible(true);
                    field.set(object,drawable);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Color 资源字符串 **/
    private static void initColor(Object object, View view) {
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Color initView = field.getAnnotation(GT_Res.GT_Color.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    int color = view.getResources().getColor(viewRes);
                    field.setAccessible(true);
                    field.set(object,color);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 String 资源字符串 **/
    private static void initString(Object object, View view) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_String initView = field.getAnnotation(GT_Res.GT_String.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    String string = view.getResources().getString(viewRes);
                    field.setAccessible(true);
                    field.set(object,string);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 Int 资源字符串数组 **/
    private static void initIntArray(Object object, View view) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_IntArray initView = field.getAnnotation(GT_Res.GT_IntArray.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    int[] intArray = view.getResources().getIntArray(viewRes);
                    field.setAccessible(true);
                    field.set(object,intArray);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 String 资源字符串数组 **/
    private static void initStringArray(Object object, View view) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_StringArray initView = field.getAnnotation(GT_Res.GT_StringArray.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    String[] stringArray = view.getResources().getStringArray(viewRes);
                    field.setAccessible(true);
                    field.set(object,stringArray);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 解析 Layout 资源文件成 View **/
    private static void initLayout(Object object, View view) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Layout initView = field.getAnnotation(GT_Res.GT_Layout.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    Context context = view.getContext();
                    if(context != null){
                        View viewLayout = LayoutInflater.from(context).inflate(viewRes, null);
                        field.setAccessible(true);
                        field.set(object,viewLayout);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 List 资源字符串 **/
    private static void initList(Object object) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            Collection.List initView = field.getAnnotation(Collection.List.class);
            if(initView!=null){
                Class[] classes = initView.value();
                List<Object> objectList = new ArrayList<>();//创建一个 ListView
                for(Class cla : classes){

                    String classPage = cla.toString();
                    String[] s = classPage.split(" ");
                    classPage = s[1];

                    //实例化一个对象
                    Object object2 = null;
                    try {
                        object2 = Class.forName(classPage).newInstance();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    objectList.add(object2);//添加每一个经过反射得到的 对象
                }
                try {
                    field.setAccessible(true);
                    field.set(object,objectList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 Map 资源字符串 **/
    private static void initMap(Object object) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            Collection.Map initView = field.getAnnotation(Collection.Map.class);
            if(initView!=null){
                Class[] classes = initView.value();
                Map<Object,Object> objectMap = new HashMap<>();//创建一个 Map
                for(Class cla : classes){

                    String classPage = cla.toString();
                    String[] s = classPage.split(" ");
                    classPage = s[1];

                    //实例化一个对象
                    Object object2 = null;
                    try {
                        object2 = Class.forName(classPage).newInstance();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    objectMap.put(cla,object2);//保存每个创建出来的 对象 key 为 每个对象的 class
                }
                try {
                    field.setAccessible(true);
                    field.set(object,objectMap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 Set 资源字符串 **/
    private static void initSet(Object object) {

        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            Collection.Set initView = field.getAnnotation(Collection.Set.class);
            if(initView!=null){
                Class[] classes = initView.value();
                Set<Object> objectSet = new HashSet<>();//创建一个 Set
                for(Class cla : classes){

                    String classPage = cla.toString();
                    String[] s = classPage.split(" ");
                    classPage = s[1];

                    //实例化一个对象
                    Object object2 = null;
                    try {
                        object2 = Class.forName(classPage).newInstance();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    objectSet.add(object2);//保存每个创建出来的 对象
                }
                try {
                    field.setAccessible(true);
                    field.set(object,objectSet);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }





    /**
     * Activity 中的使用
     */

    /**
     * activity 注入
     * @param activity
     */
    public static void initAll(Activity activity){

        initActivity(activity);             //为加载 Activity 布局初始化
        initView(activity);                 //为加载 组件 初始化
        initClick(activity);                //为加载 组件单击 初始化

        initObject(activity);               //为加载 Object 成员变量初始化

        initAnimation(activity);            //为加载 Animation 资源初始化
        initDimen(activity);                //为加载 Dimen 资源初始化
        initDrawable(activity);             //为加载 Style 资源初始化
        initColor(activity);                //为加载 Color 资源初始化
        initString(activity);               //为加载 String 资源初始化

        initIntArray(activity);             //为加载 IntArray 资源初始化
        initStringArray(activity);          //为加载 StringArray 资源初始化

        initLayout(activity);               //为加载 Layout 资源初始化

    }


    /** 解析 Layout 资源文件成 View **/
    private static void initLayout(Activity activity) {

        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Layout initView = field.getAnnotation(GT_Res.GT_Layout.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    View view = LayoutInflater.from(activity).inflate(viewRes, null);
                    field.setAccessible(true);
                    field.set(activity,view);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 Int 资源字符串数组 **/
    private static void initIntArray(Activity activity) {

        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_IntArray initView = field.getAnnotation(GT_Res.GT_IntArray.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    int[] intArray = activity.getResources().getIntArray(viewRes);
                    field.setAccessible(true);
                    field.set(activity,intArray);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 String 资源字符串数组 **/
    private static void initStringArray(Activity activity) {

        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_StringArray initView = field.getAnnotation(GT_Res.GT_StringArray.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    String[] stringArray = activity.getResources().getStringArray(viewRes);
                    field.setAccessible(true);
                    field.set(activity,stringArray);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /** 注入 Animation 资源字符串 **/
    private static void initAnimation(Activity activity) {
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Animation initView = field.getAnnotation(GT_Res.GT_Animation.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    Animation animation = AnimationUtils.loadAnimation(activity, viewRes);
                    field.setAccessible(true);
                    field.set(activity,animation);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Dimen 资源字符串 **/
    private static void initDimen(Activity activity) {
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Dimen initView = field.getAnnotation(GT_Res.GT_Dimen.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    float dimension = activity.getResources().getDimension(viewRes);
                    field.setAccessible(true);
                    field.set(activity,dimension);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Drawable 资源字符串 **/
    private static void initDrawable(Activity activity) {
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Drawable initView = field.getAnnotation(GT_Res.GT_Drawable.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    Drawable drawable = activity.getResources().getDrawable(viewRes);
                    field.setAccessible(true);
                    field.set(activity,drawable);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 Color 资源字符串 **/
    private static void initColor(Activity activity) {
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_Color initView = field.getAnnotation(GT_Res.GT_Color.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    int color = activity.getResources().getColor(viewRes);
                    field.setAccessible(true);
                    field.set(activity,color);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /** 注入 String 资源字符串 **/
    private static void initString(Activity activity) {

        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Res.GT_String initView = field.getAnnotation(GT_Res.GT_String.class);
            if(initView!=null){
                int viewRes = initView.value();
                try {
                    String string = activity.getResources().getString(viewRes);
                    field.setAccessible(true);
                    field.set(activity,string);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 参数版
     * @param object
     */
    private static void initObject(Object object){
        Class<? extends Object> clazz = object.getClass();//获取该类信息
        Field[] fields = clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_Object initView = field.getAnnotation(GT_Object.class);

            if(initView != null){

                //获取 完整的类路径
                String classPage = field.toString();
                String[] s = classPage.split(" ");
                classPage = s[1];

                //实例化一个对象
                Object object2 = null;
                try {
                    object2 = Class.forName(classPage).newInstance();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }


                //获取参数的值类型
                String type = initView.type();
                String[] types = initView.types();


                //创建保存 参数类型的容器
                List<Object> valueList = new ArrayList<>();
                if(type.length() != 0){
                    valueType(type,valueList,initView,0);//将当前的单个数据赋值到 listView 中
                }else if(types.length != 0){
                    for(int i = 0; i < types.length; i++){
                        valueType(types[i],valueList,initView,i);//将当前的多个数据赋值到 listView 中
                    }
                }
                String function = initView.function();
                String[] functions = initView.functions();

                /**
                 * 获取当前方法所有方法
                 */
                if(function.length() != 0 && valueList.size() != 0){
                    functionValue(field,object2,function,valueList,0);//对相应的方法进行赋值
                }else if(functions.length != 0 && valueList.size() != 0){
                    for(int i = 0; i < functions.length; i++){
                        functionValue(field,object2,functions[i],valueList,i);//对相应的方法进行赋值
                    }
                }


                //给注解下面的 成员变量注入值
                try {
                    field.setAccessible(true);
                    field.set(object,object2);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private static void functionValue(Field field, Object object, String functionName, List<Object> valueList, int index){

        if(functionName.length() != 0 && valueList.size() != 0){

            Class<?> aClass = object.getClass();
            Method[] methods = aClass.getMethods();

            //获取当前类中所有方法
            for(int i = methods.length-1; i >= 0 ; i--){
                String name = methods[i].getName();
                if(name.equals(functionName)){
                    try {
                        Method method = getAllValueTypeMethod(valueList.get(index),functionName,aClass);
                        method.setAccessible(true);
                        field.setAccessible(true);
                        method.invoke(object, valueList.get(index));
                    } catch (Exception e) {
                        GT.log_i("赋值报错");
                        e.printStackTrace();
                    }
                }
            }
        }

    }


    /**
     * 自获取当前传入数据的类型
     * @param data
     * @param functionName
     * @param aClass
     * @return
     */
    private static Method getAllValueTypeMethod(Object data, String functionName, Class<?> aClass){

        Method method = null;

        Class<?> aClass1 = data.getClass();
        switch (aClass1.toString()){
            case "class java.lang.Byte":
                try {
                    method =  aClass.getMethod(functionName, byte.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Short":
                try {
                    method =  aClass.getMethod(functionName, short.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Integer":
                try {
                    method =  aClass.getMethod(functionName, int.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Long":
                try {
                    method =  aClass.getMethod(functionName, long.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Float":
                try {
                    method =  aClass.getMethod(functionName, float.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Double":
                try {
                    method =  aClass.getMethod(functionName, double.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Boolean":
                try {
                    method =  aClass.getMethod(functionName, boolean.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.Character":
                try {
                    method =  aClass.getMethod(functionName, char.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
            case "class java.lang.String":
                try {
                    method =  aClass.getMethod(functionName, String.class);
                } catch (NoSuchMethodException e) {
//                    e.printStackTrace();
                }
                break;
        }
        return method;
    }


    /**
     * 给 listView 赋值
     * @param type
     * @param list
     * @param values
     */
    private static void valueType(String type, List<Object> list, GT_Object values, int index){

        switch (type){

            /** 单个参数的赋值 **/
            case "byte":
                list.add(values.valueByte());
                break;
            case "short":
                list.add(values.valueShort());
                break;
            case "int":
                list.add(values.valueInt());
                break;
            case "long":
                list.add(values.valueLong());
                break;
            case "float":
                list.add(values.valueFloat());
                break;
            case "double":
                list.add(values.valueDouble());
                break;
            case "boolean":
                list.add(values.valueBoolean());
                break;
            case "char":
                list.add(values.valueChar());
                break;
            case "String":
                list.add(values.valueString());
                break;

            /** 多个参数的赋值 **/
            case "bytes":
                byte[] bytes = values.valueBytes();
                for(byte value:bytes){
                    list.add(value);
                }
                break;
            case "shorts":
                short[] shorts = values.valueShorts();
                list.add(shorts[index]);
                break;
            case "ints":
                int[] ints = values.valueInts();
                list.add(ints[index]);
                break;
            case "longs":
                long[] longs = values.valueLongs();
                list.add(longs[index]);
                break;
            case "floats":
                float[] floats = values.valueFloats();
                list.add(floats[index]);
                break;
            case "doubles":
                double[] doubles = values.valueDoubles();
                list.add(doubles[index]);
                break;
            case "booleans":
                boolean[] booleans = values.valueBooleans();
                list.add(booleans[index]);
                break;
            case "chars":
                char[] chars = values.valueChars();
                list.add(chars[index]);
                break;
            case "Strings":
                String[] strings = values.valueStrings();
                list.add(strings[index]);
                break;
        }

    }


    /**
     * 注入 ContextView
     * @param activity
     */
    private static void initActivity(Activity activity){
        Class<? extends Activity> mClass = activity.getClass();//获取该类信息
        GT_Activity contentView = mClass.getAnnotation(GT_Activity.class);//获取该类 ContextView 的注解类
        //如果有注解
        if(contentView != null){
            int viewId = contentView.value();//获取注解类参数
            try {
                Method method = mClass.getMethod("setContentView",int.class);//获取该方法的信息
                method.setAccessible(true);//获取该方法的访问权限
                method.invoke(activity,viewId);//调用该方法的,并设置该方法参数
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     *注入控件
     * @param activity
     */
    private static void initView(Activity activity){
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
        for (Field field:fields) {
            GT_View initView = field.getAnnotation(GT_View.class);
            if(initView!=null){
                int viewId=initView.value();
                try {
                    Method method = clazz.getMethod("findViewById", int.class);
                    method.setAccessible(true);
                    field.setAccessible(true);
                    Object object = method.invoke(activity, viewId);
                    field.set(activity,object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 注入点击事件
     * @param activity
     */
    private static void initClick(Activity activity){
        Class<? extends Activity> clazz = activity.getClass();
        Method[] methods= clazz.getMethods();//获取所有声明为公有的方法
        for (Method method:methods){//遍历所有公有方法
            Annotation[] annotations = method.getAnnotations();//获取该公有方法的所有注解
            for (Annotation annotation:annotations){//遍历所有注解
                Class<? extends Annotation> annotationType = annotation.annotationType();//获取具体的注解类
                OnClickEvent onClickEvent = annotationType.getAnnotation(OnClickEvent.class);//取出注解的onClickEvent注解
                if(onClickEvent!=null){//如果不为空
                    try {
                        Method valueMethod=annotationType.getDeclaredMethod("value");//获取注解InjectOnClick的value方法
                        int[] viewIds= (int[]) valueMethod.invoke(annotation, (Object[]) null);//获取控件值
                        Class<?> listenerType = onClickEvent.listenerType();//获取接口类型
                        String listenerSetter = onClickEvent.listenerSetter();//获取set方法
                        String methodName = onClickEvent.methodName();//获取接口需要实现的方法
                        MyInvocationHandler handler = new MyInvocationHandler(activity);//自己实现的代码,负责调用
                        handler.setMethodMap(methodName,method);//设置方法及设置方法
                        Object object= Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},handler);//创建动态代理对象类
                        for (int viewId:viewIds){//遍历要设置监听的控件
                            View view=activity.findViewById(viewId);//获取该控件
                            Method m=view.getClass().getMethod(listenerSetter, listenerType);//获取方法
                            m.invoke(view,object);//调用方法
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //注解帮助类
    static class MyInvocationHandler implements InvocationHandler {

        private Object object;
        private Map<String, Method> methodMap = new HashMap<>(1);
        public MyInvocationHandler(Object object) {
            this.object = object;
        }
        public void setMethodMap(String name, Method method) {
            this.methodMap.put(name, method);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (object != null) {
                String name = method.getName();
                method= this.methodMap.get(name);
                if (method != null) {
                    return method.invoke(object, args);
                }
            }
            return null;
        }

    }

}

一下子码这么多,我也是第一次写博客写这么多,我们休息一下,我们看个美景,缓缓眼睛疲劳

接下来,我们就只欠东风了。

第三步:新建必要的文件:

LoginBean、Fragment_1、Fragment_2、Fragment_3

LoginBean:代码如下

public class LoginBean {

    private String username;
    private String password;
    private int age;

    public void setAge(int age) {
        this.age = age;
    }

    public LoginBean() {
        super();
    }

    public LoginBean(String username, String password, int age) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "LoginBean{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

}

Fragment_1:代码如下

public class Fragment_1 extends Fragment {

    private static final String TAG = "GT_";

    public static Fragment_1 newInstance() {
        Bundle args = new Bundle();
        Log.i(TAG,"Fragment_1 newInstance");
        Fragment_1 fragment = new Fragment_1();
        fragment.setArguments(args);
        return fragment;
    }

    public Fragment_1(){
        Log.i(TAG,"Fragment_1");
    }

}

Fragment_2:代码如下

public class Fragment_2 extends Fragment {

    private static final String TAG = "GT_";

    public static Fragment_2 newInstance() {
        Bundle args = new Bundle();
        Log.i(TAG,"Fragment_2 newInstance");
        Fragment_2 fragment = new Fragment_2();
        fragment.setArguments(args);
        return fragment;
    }

    public Fragment_2(){
        Log.i(TAG,"Fragment_2");
    }

}

Fragment_3:代码如下

public class Fragment_3 extends Fragment {

    private static final String TAG = "GT_";

    public static Fragment_3 newInstance() {
        Bundle args = new Bundle();
        Log.i(TAG,"Fragment_3 newInstance");
        Fragment_3 fragment = new Fragment_3();
        fragment.setArguments(args);
        return fragment;
    }

    public Fragment_3(){
        Log.i(TAG,"Fragment_3");
    }

}

第四步:添加测试资源文件

alpha.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- alpha 设置透明度
        fromAlpha :  起始点的透明度
        toAlpha   :  结束点的透明度
        duration  :  设置透明度渐变的时间 已毫秒为单位
        repeatCount: 设置重复次数
        repeatMode:  reverse(反向) | restart(重新开始)  设置重复方式
    -->
    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"
        android:duration="2000"
        />

</set>

activity_main.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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/ioc_tv"
        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" />

    <Button
        android:id="@+id/ioc_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="单击测试"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.603" />


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toTopOf="@+id/ioc_tv"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <Button
            android:id="@+id/ioc_btn01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮1" />

        <Button
            android:id="@+id/ioc_btn02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮2" />

        <Button
            android:id="@+id/ioc_btn03"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮3" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

arrays.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--定义字符串元素-->
    <string-array name="ctype">
        <item>全部</item>
        <item>电影</item>
        <item>娱乐</item>
        <item>图书</item>
        <item>运动</item>
    </string-array>

    <!--定义整数类型数组-->
    <integer-array name="textInt">
        <item>1</item>
        <item>2</item>
        <item>3</item>
    </integer-array>

</resources>

colors.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="colorTest">#FFE700</color>
</resources>

dimens.xml 代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--定义尺寸资源-->
    <dimen name="tv_size">10sp</dimen>

</resources>

strings.xml 代码:

<resources>
    <string name="app_name">Butter Knife(小刀注解)</string>

    <string name="StringTest">测试数据</string>
</resources>

最后步:添加测试代码

MainActivity.java 代码:

@GT_Activity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {

    @GT_View(R.id.ioc_tv)
    private TextView tv;

    @GT_View(R.id.ioc_btn)
    private Button btn;

    @GT_Object(valueString = "1079",valueInt = 21,types = {GT_Object.TYPE.STRING, GT_Object.TYPE.INT}, functions = {"setUsername","setAge"})
    private LoginBean loginBean;

    @GT_Res.GT_String(R.string.StringTest)
    private String data;

    @GT_Res.GT_Color(R.color.colorTest)
    private int MyColor;

    @GT_Res.GT_Drawable(R.drawable.ic_launcher_background)
    private Drawable btnBG;

    @GT_Res.GT_Dimen(R.dimen.tv_size)
    private float TextSize;

    @GT_Res.GT_Animation(R.anim.alpha)
    private Animation animation;

    @GT_Res.GT_StringArray(R.array.ctype)
    private String[] strArray;

    @GT_Res.GT_IntArray(R.array.textInt)
    private int[] intArray;

    @GT_Res.GT_Layout(R.layout.activity_main)
    private View layout;

    private static final String TAG = "GT_";

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GT_Util.initAll(this);//绑定 Activity
        GT.log_e( "onCreate: tv = " + tv + " btn:" + btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Log.i(TAG,"loginBean: " + loginBean);
                Log.i(TAG,"data: " + data);
                Log.i(TAG,"color: " + MyColor);
                Log.i(TAG,"Drawable: " + btnBG);
                Log.i(TAG,"TextSize: " + TextSize);
                Log.i(TAG,"animation: " + animation);
                Log.i(TAG,"strArray: " + strArray);
                Log.i(TAG,"intArray: " + intArray);
                Log.i(TAG,"layout: " + layout);

                tv.setText("实现成功!");
                btn.setTextColor(MyColor);
                btn.setTextSize(TextSize);
                btn.setBackgroundDrawable(btnBG);
                btn.startAnimation(animation);

            }
        });

    }

    @GT_Click({R.id.ioc_btn01,R.id.ioc_btn02,R.id.ioc_btn03})
    public void testBtnOnCLick(View view){
        switch (view.getId()){
            case R.id.ioc_btn01:
                Log.i(TAG,"单击 1 号" );
                break;

            case R.id.ioc_btn02:
                Log.i(TAG,"单击 2 号" );
                break;

            case R.id.ioc_btn03:
                Log.i(TAG,"单击 3 号" );
                break;
        }
    }

}

终于完成了所有代码的编写,现在我们来看看你花这10分钟到底值不值吧。٩(๑>◡<๑)۶ 

运行效果图:

打印日志:

08-30 12:11:33.918 3723-3723/com.gsls.myapplication E/GT_e: ------- onCreate: tv = androidx.appcompat.widget.AppCompatTextView{5552d29 V.ED.... ......ID 0,0-0,0 #7f08004d app:id/ioc_tv} btn:androidx.appcompat.widget.AppCompatButton{fbce8ae VFED..C. ......I. 0,0-0,0 #7f080049 app:id/ioc_btn}
08-30 12:11:41.841 3723-3723/com.gsls.myapplication I/GT_: 单击 1 号
08-30 12:11:42.408 3723-3723/com.gsls.myapplication I/GT_: 单击 2 号
08-30 12:11:43.001 3723-3723/com.gsls.myapplication I/GT_: 单击 3 号
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: loginBean: LoginBean{username='1079', password='null', age=21}
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: data: 测试数据
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: color: -6400
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: Drawable: android.graphics.drawable.VectorDrawable@2280d25b
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: TextSize: 10.0
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: animation: android.view.animation.AnimationSet@3e537af8
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: strArray: [Ljava.lang.String;@cd31bd1
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: intArray: [I@1d02b636
08-30 12:11:44.255 3723-3723/com.gsls.myapplication I/GT_: layout: androidx.constraintlayout.widget.ConstraintLayout{11703937 V.E..... ......I. 0,0-0,0}
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: loginBean: LoginBean{username='1079', password='null', age=21}
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: data: 测试数据
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: color: -6400
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: Drawable: android.graphics.drawable.VectorDrawable@2280d25b
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: TextSize: 10.0
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: animation: android.view.animation.AnimationSet@3e537af8
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: strArray: [Ljava.lang.String;@cd31bd1
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: intArray: [I@1d02b636
08-30 12:11:45.909 3723-3723/com.gsls.myapplication I/GT_: layout: androidx.constraintlayout.widget.ConstraintLayout{11703937 V.E..... ......I. 0,0-0,0}

总结:看我这么辛苦。 点个关注呗<(▰˘◡˘▰)>

关注博主最新发布库:https://github.com/1079374315/GT

本篇文章源码地址:github地址:GitHub - 1079374315/GT_IOC: 教你10分钟手敲 Butter Knife(小刀注解)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PlayfulKing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值