教你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("卡哇伊");//使用组件
}
}
在实际项目中有什么好处呢?
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(小刀注解)