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

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

1. Give a beautiful morning to us

上篇我们说了下控件注解,其中有用到invoke去执行findviewbyid方法获取控件。既然方法名称可以被获取到,然后invoke方法,那事件注解的形式,我们考虑下用方法名称作为参数,暂时还是不考虑定义method的形式,采用如下形式:

2. 走走走

我们就去定义OnClick注解类(分别包含控件和事件名称)

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.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
    int value();                    ///< 控件id
    String onClick() default "";    ///< 点击事件名称
}

现在我们就去实现注解解析,好伐 - 重点部分:///< 2.如果是事件注解类型

package com.example.mylibrary;

import android.app.Activity;
import android.content.Context;
import android.view.View;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Author: hl
 * Time:  2018/5/23 11:21
 * Des:   This is not really ButterKnife
 */
public class ButterKnife {
    /**
     * 注解绑定
     * @param context
     */
    public static void bind(final Context context) {
        ///< 0\. 获取Class类
        Class classObj = context.getClass();
        ///< 1.获取Field数组
        //Field[] fields = classObj.getFields();        ///< 只能获取public声明的,ButterKnife用的应该是这种
        Field[] fields = classObj.getDeclaredFields();  ///< public和private的都可以获取
        for (Field field : fields){
            ///< 2.判断是否添加了BindView注解,如果是我们则可以获取控件id
            if (field.isAnnotationPresent(BindView.class)){
                ///< 3.获取注解实例
                BindView bindView = field.getAnnotation(BindView.class);
                ///< 4.获取上面的控件id
                //int viewId = bindView.viewId();
                int viewId = bindView.value();
                ///< 判断下上下文类型吧!(真正的Butterknife在不同类型界面使用方法有区别)
                if (context instanceof Activity){
                    ///< 5.我们暂时用以前常用的findviewbyid来获取控件吧
                    //Object viewObj = ((Activity)context).findViewById(viewId);
                    try {
                        ///< 5.two 用反射获取方法,进而执行获取控件
                        Method method = classObj.getMethod("findViewById", int.class);
                        Object viewObj = method.invoke(context, viewId);
                        ///< 6.将获取的控件设置到file上面
                        ///< 注意,如果控件类型声明的是private的,这里需要添加;
                        ///<       如果是public的,可以不用添加;
                        field.setAccessible(true);
                        field.set(context, viewObj);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }

            ///< 2.如果是事件注解类型
            if (field.isAnnotationPresent(OnClick.class)){
                OnClick onClick = field.getAnnotation(OnClick.class);
                ///< 3.获取控件id和方法名称
                final int viewId = onClick.value();
                String funcName = onClick.onClick();

                try {
                    ///< 4\. 给控件变量赋值
                    final Method method = classObj.getMethod("findViewById", int.class);
                    final Object viewObj = method.invoke(context, viewId);
                    field.setAccessible(true);
                    field.set(context, viewObj);

                    ///< 5.执行方法
                    final Method methodClick = classObj.getMethod(funcName, View.class);
                    ///< 5.0\. 给控件设置点击监听事件(别的方法后面我们再说...先来常规笨的常用的这种)
                    ((View)viewObj).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            try {
                                ///< 5.1 然后执行方法
                                methodClick.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();
                }
            }
        }
    }
}

然后测试下,重点: 点击事件定义

package com.example.lieyun_android.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.example.mylibrary.BindView;
import com.example.mylibrary.ButterKnife;
import com.example.mylibrary.OnClick;

public class MainActivity extends AppCompatActivity {

    //@BindView(viewId = R.id.testSB)
    @BindView(R.id.testSB)
    private TextView sb;

    @OnClick(value = R.id.testSB, onClick = "funckSb")
    public TextView sb2;

    /**
     * 点击事件定义
     * @param view
     */
    public void funckSb(View view){
        sb.setText("fuck sb 2");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ///< 注解绑定
        ButterKnife.bind(this);
        ///< 使用下控件,么么哒
        sb.setText("fuck sb");
    }
}
image

下一部分(打算下周继续,这样又可以回顾相关知识,有助于不停的反复加深使用和理解)我们继续别的形式的定义(重点就是@Target(ElementType.METHOD)...想想其实这些东西还是有点意思的哇

相关文章

网友评论

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

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