注解+反射实现android绑定控件和页面跳转传参
工具类InjectUtils:
public class InjectUtils {
public static void injectView(Activity activity) {
Class<? extends Activity> cls = activity.getClass();
//获得此类所有的成员
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
//判断注解是否被InjectView声明
if (field.isAnnotationPresent(InjectView.class)) {
InjectView injectView = field.getAnnotation(InjectView.class);
//获得了注解中设置的id
int id = injectView.value();
View view = activity.findViewById(id);
//反射设置属性的值
field.setAccessible(true); //设置访问权限,允许操作private的属性
try {
//反射赋值
field.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static void injectAutowired(Activity activity) {
Class<? extends Activity> cls = activity.getClass();
//获取数据
Intent intent = activity.getIntent();
Bundle extras = intent.getExtras();
if (extras == null) {
return;
}
//获取此类的所有的成员
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(Autowired.class)) {
Autowired autowired = field.getAnnotation(Autowired.class);
//获得key
String key = TextUtils.isEmpty(autowired.value())?field.getName() : autowired.value();
if (extras.containsKey(key)) {
Object obj = extras.get(key);
//todo Parcelable数组类型不能直接设置,其他的都可以
//获得数组单个元素类型
Class<?> componentType = field.getType().getComponentType();
//当前属性是数组并且Parcelable(子类)数组
if (field.getType().isArray() &&
Parcelable.class.isAssignableFrom(componentType)) {
Object[] objs = (Object[]) obj;
//创建对应类型的数组并由objs拷贝
Object[] objects = Arrays.copyOf(objs, objs.length, (Class<? extends Object[]>) field.getType());
obj = objects;
}
field.setAccessible(true);
try {
field.set(activity,obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
public static void injectEvent(Activity activity) {
Class<? extends Activity> activityClass = activity.getClass();
Method[] declaredMethods = activityClass.getDeclaredMethods();
for (Method method : declaredMethods) {
//获得方法上所有注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
//注解类型
Class<? extends Annotation> annotationType = annotation.annotationType();
if (annotationType.isAnnotationPresent(EventType.class)) {
EventType eventType = annotationType.getAnnotation(EventType.class);
// OnClickListener.class
Class listenerType = eventType.listenerType();
//setOnClickListener
String listenerSetter = eventType.listenerSetter();
try {
// 不需要关心到底是OnClick 还是 OnLongClick
Method valueMethod = annotationType.getDeclaredMethod("value");
int[] viewIds = (int[]) valueMethod.invoke(annotation);
method.setAccessible(true);
ListenerInvocationHandler<Activity> handler = new ListenerInvocationHandler(activity, method);
Object listenerProxy = Proxy.newProxyInstance(listenerType.getClassLoader(),
new Class[]{listenerType}, handler);
// 遍历注解的值
for (int viewId : viewIds) {
// 获得当前activity的view(赋值)
View view = activity.findViewById(viewId);
// 获取指定的方法(不需要判断是Click还是LongClick)
// 如获得:setOnClickLisnter方法,参数为OnClickListener
// 获得 setOnLongClickLisnter,则参数为OnLongClickLisnter
Method setter = view.getClass().getMethod(listenerSetter, listenerType);
// 执行方法
setter.invoke(view, listenerProxy); //执行setOnclickListener里面的回调 onclick方法
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/**
* 还可能在自定义view注入,所以是泛型: T = Activity/View
*
* @param <T>
*/
static class ListenerInvocationHandler<T> implements InvocationHandler {
private Method method;
private T target;
public ListenerInvocationHandler(T target, Method method) {
this.target = target;
this.method = method;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return this.method.invoke(target, args);
}
}
}
注解类InjectView:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
@IdRes int value();
}
自定义元注解类:
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {
Class listenerType();
String listenerSetter();
}
注解类OnClick:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnClickListener.class, listenerSetter = "setOnClickListener")
public @interface OnClick {
int[] value();
}
注解类OnLongClick:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnLongClickListener.class,listenerSetter = "setOnLongClickListener")
public @interface OnLongClick {
int[] value();
}
注解类Autowired:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
String value();
}
MainActivity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@InjectView(R.id.tv)
private TextView textView;
@InjectView(R.id.button)
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.injectView(this);
InjectUtils.injectEvent(this);
textView.setText("邵佳豪真tm的帅");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,TwoActivity.class).putExtra("name","邵佳豪年薪百万!");
startActivity(intent);
}
});
}
@OnClick({R.id.btn1,R.id.btn2})
public void click(View view) {
switch (view.getId()) {
case R.id.btn1:
Log.i(TAG,"click:按钮1");
break;
case R.id.btn2:
Log.i(TAG,"click:按钮2");
break;
}
}
@OnLongClick({R.id.btn1,R.id.btn2})
public boolean longClick(View view) {
switch (view.getId()) {
case R.id.btn1:
Log.i(TAG,"longClick:按钮1");
break;
case R.id.btn2:
Log.i(TAG,"longClick:按钮2");
break;
}
return false;
}
}
TwoActivity:
public class TwoActivity extends AppCompatActivity {
@Autowired("name")
String name;
@InjectView(R.id.tv1)
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
InjectUtils.injectView(this);
InjectUtils.injectAutowired(this);
tv.setText(name);
}
}
运行截图: