介绍
ButterKnife是一个专注于Android系统的View、Resource、Action注入框架。
这个自定义butternife可以让你充分了解其实现的原理及底层如何查找id 去使用 去传参 去定义方法 反射获取各个定义内容。
第一步写一个Annotation定义我们需要去@出来的方法
这里我写了点击事件 和 查找ID的@
InjectView
@Retention(RetentionPolicy.RUNTIME) //运行时加载 节省资源
@Target(ElementType.FIELD) //变量
public @interface InjectView {
int ID(); //传递布局id
}
OnClick点击事件
@Retention(RetentionPolicy.RUNTIME) //运行时加载 节省资源
@Target(ElementType.METHOD) //方法
public @interface OnClick {
int value(); //传递要点击的布局id
}
综合定义类 传递 activity页面重写两个方法去写出底层代码实现逻辑完成查找ID 及 点击事件
ViewUtils
public class ViewUtils {
public static void bind(Activity activity) throws Exception {
bindFeild(activity); //查找ID
bindOnClick(activity); //点击事件
}
private static void bindOnClick(final Activity activity) throws Exception {
Class<? extends Activity> aClass = activity.getClass(); //获取布局
Method[] declaredMethods = aClass.getDeclaredMethods(); //获取所有方法
for (final Method method:declaredMethods) { //遍历
OnClick annotation = method.getAnnotation(OnClick.class); //获取方法
if(annotation!=null){ //判断不为空
int value = annotation.value();
View viewById = activity.findViewById(value);
method.setAccessible(true); //暴力访问
viewById.setOnClickListener(new View.OnClickListener() { //设置点击事件
@Override
public void onClick(View v) {
try {
method.invoke(activity); //方法反射
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
private static void bindFeild(Activity activity) { //查找id
Class<? extends Activity> clazz = activity.getClass(); //获取布局
Field[] declaredFields = clazz.getDeclaredFields(); //获取所有属性
for (Field feild:declaredFields) { //遍历
InjectView annotation = feild.getAnnotation(InjectView.class);
if(annotation != null){
int resID = annotation.ID();
View viewById = activity.findViewById(resID);
feild.setAccessible(true);
try {
feild.set(activity,viewById); //实现
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
主布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<Button
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:id="@+id/btn1"/>
</RelativeLayout>
主布局代码
public class MainActivity extends AppCompatActivity {
@InjectView(ID = R.id.btn1)
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ViewUtils.bind(this); //绑定
} catch (Exception e) {
e.printStackTrace();
}
}
@OnClick(value = R.id.btn1)
private void OnClick(){
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "nice ", Toast.LENGTH_SHORT).show();
}
});
}
}
效果展示