首先我们需要现在原有的工程中新建一个Studio Model reflectlibrery
reflectlibrery 中 BindOnclick
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD,ElementType.METHOD})
public @interface BindOnclick {
int [] value() default -1;
}
reflectlibrery 中 ImitationDeclared
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ImitationDeclared {
int value() default -1;
}
reflectlibrery 中 InjectView
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectView {
int value() default -1;
}
reflectlibrery 中 ButtknifeUtils
package jiaoyibo.bawei.com.reflectlibrery;
import android.app.Activity;
import android.graphics.Paint;
import android.view.View;
import android.widget.TextView;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* <p>文件描述:<p>
* <p>作者:JYB<p>
* <p>创建时间:2019/3/13<p>
* <p>更改时间:2019/3/13<p>
* <p>版本号:1<p>
*/
public class ButtknifeUtils {
public static void injectView(final Activity activity) throws IllegalAccessException{
//找到被InjectView注解的控件 2、通过反射拿到注解中的资源 3、通过findViewById把xml中的对象绑定给 被注解修饰的控件
Class<Activity> aClass = (Class<Activity>) activity.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
//帮助我们findViewById
for (Field field:declaredFields){
//该属性是否被InjectView注解修饰
if(field.isAnnotationPresent(InjectView.class)){
InjectView annotation = field.getAnnotation(InjectView.class);
int id = annotation.value();
View view = activity.findViewById(id);
//可访问
field.setAccessible(true);
//给控件赋值
field.set(activity,view);
if(field.isAnnotationPresent(ImitationDeclared.class)){
if(view instanceof TextView){
((TextView)view).getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
}
}
}
}
//帮助我们找点击事件的方法
Method[] declareMethods = aClass.getDeclaredMethods();
for(final Method method:declareMethods){
//该属性是否被InjectView注解修饰
if(method.isAnnotationPresent(BindOnclick.class)){
//获取注解对象,为了拿注解中的属性 id
BindOnclick annotation = method.getAnnotation(BindOnclick.class);
int[] ids = annotation.value();
for(int id:ids){
View view = activity.findViewById(id);
//可访问
method.setAccessible(true);
//给控件赋值
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
//调用一下被BindOnclick注解修饰的方法
method.invoke(activity,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
写完之后,别忘了到依赖库关联一下
接着就在自己的项目中新建一个person数据
package jiaoyibo.bawei.com.zhujie;
/**
* <p>文件描述:<p>
* <p>作者:JYB<p>
* <p>创建时间:2019/3/13<p>
* <p>更改时间:2019/3/13<p>
* <p>版本号:1<p>
*/
@Deprecated
public class Person {
private String name;
public int age;
public Person(){
}
@Deprecated
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Deprecated
public Person(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
@Deprecated
public int getAge() {
return age;
}
}
接着创建ReflctTest
package jiaoyibo.bawei.com.zhujie;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* <p>文件描述:<p>
* <p>作者:JYB<p>
* <p>创建时间:2019/3/13<p>
* <p>更改时间:2019/3/13<p>
* <p>版本号:1<p>
*/
public class ReflctTest {
public static void main(String[] arggs) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//方式一
Class<Person> personClass = Person.class;
//方式二
Class<Person> aClass = (Class<Person>) Class.forName("jiaoyibo.bawei.com.zhujie");
//方式三
Person person = new Person("ddd",2);
Class<Person> aClass2 = (Class<Person>) person.getClass();
//在class中拿field,所有public属性
Field[] fields = personClass.getFields();
//在class中拿field,所有属性
Field[] declaredFields = personClass.getDeclaredFields();
System.out.println("======================"+ (fields.length>=declaredFields.length));
Field field = personClass.getDeclaredField("name");
//设置可访问、可以拿到私有的属性
field.setAccessible(true);
field.get(person);
System.out.println("======================"+ field.get(person));
Method getName = personClass.getDeclaredMethod("getName");
getName.setAccessible(true);
//方法对象调用方式 method.invoke(他所属的对象,方法的形参)
getName.invoke(person);
System.out.println("======================"+ getName.invoke(person));
//通过反射拿到构造器,去构造一个对象
Constructor<Person> constructor = personClass.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
Person person1 = constructor.newInstance("1510B",3);
System.out.println("======================"+ person1.getAge());
}
}
接下来就是我们的主页面
package jiaoyibo.bawei.com.zhujie;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import jiaoyibo.bawei.com.reflectlibrery.BindOnclick;
import jiaoyibo.bawei.com.reflectlibrery.ButtknifeUtils;
import jiaoyibo.bawei.com.reflectlibrery.ImitationDeclared;
import jiaoyibo.bawei.com.reflectlibrery.InjectView;
public class MainActivity extends AppCompatActivity {
@ImitationDeclared()
@InjectView(R.id.reflect_id)
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ButtknifeUtils.injectView(this);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
textView.setText("我是自定义注解做出来的");
}
@BindOnclick(value = {R.id.image_test,R.id.image_test2})
public void onclick(View view){
switch (view.getId()){
case R.id.image_test:
Toast.makeText(this, "我是测试的自定义点击注解", Toast.LENGTH_LONG).show();
break;
case R.id.image_test2:
Toast.makeText(this, "我是测试的自定义点击注解22222222", Toast.LENGTH_LONG).show();
break;
}
}
}
下面是主页面的布局
<?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">
<TextView
android:id="@+id/reflect_id"
android:textSize="30sp"
android:textColor="#ff0000"
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" />
<ImageView
android:id="@+id/image_test"
android:background="@color/colorPrimary"
android:layout_centerInParent="true"
android:layout_width="150dp"
android:layout_height="150dp" />
<ImageView
android:id="@+id/image_test2"
android:layout_below="@+id/image_test"
android:background="@color/colorAccent"
android:layout_centerInParent="true"
android:layout_width="150dp"
android:layout_height="150dp" />
</RelativeLayout>