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");
}
}
![](https://img.haomeiwen.com/i12874069/cf404aa4442c70f7.jpg)
下一部分(打算下周继续,这样又可以回顾相关知识,有助于不停的反复加深使用和理解)我们继续别的形式的定义(重点就是@Target(ElementType.METHOD)...想想其实这些东西还是有点意思的哇
网友评论