2021助理高薪-拉钩产品经理高薪训练营

download:2021助理高薪-拉钩产品经理高薪训练营 运用反射和动态代理完成一个View注解绑定库
支持的功用
@ContentView 绑定layout 替代setContentView()
@BindView 绑定View 替代findViewById()
@OnClick 绑定点击事情 替代setOnClickListener()
@OnLongClick 绑定长按事情 替代setOnLongClickListener()
代码
注解类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {

int value();

}
复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
int value();

}
复制代码
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnEvent {
//订阅方式 String setCommonListener(); //事情源对象 Class commonListener();

}
复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@OnEvent(setCommonListener = "setOnClickListener",
commonListener = View.OnClickListener.class)

【2021助理高薪-拉钩产品经理高薪训练营】public @interface OnClick {
int value();

}
复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@OnEvent(setCommonListener = "setOnLongClickListener",
commonListener = View.OnLongClickListener.class)

public @interface OnLongClick {
int value();

}
复制代码
完成类
public class MsInjector {
public static void inject(Object object) { injectContentView(object); injectView(object); injectEvent(object); } private static void injectContentView(Object object) { Class clazz = object.getClass(); //获取到ContentView注解 ContentView contentView = clazz.getAnnotation(ContentView.class); if (contentView == null) { return; } //获取到注解的值,也就是layoutResID int layoutResID = contentView.value(); try { //反射出setContentView办法并调用 Method method = clazz.getMethod("setContentView", int.class); method.invoke(object, layoutResID); } catch (Exception e) { e.printStackTrace(); } } private static void injectView(Object object) { Class clazz = object.getClass(); //获取到一切字段并遍历 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); //获取字段上的BindView注解 BindView bindView = field.getAnnotation(BindView.class); if (bindView == null) { continue; } //获取到viewId int viewId = bindView.value(); try { //经过反射调用findViewById得到view实例对象 Method method = clazz.getMethod("findViewById", int.class); Object view = method.invoke(object, viewId); //赋值给注解标注的对应字段 field.set(object, view); } catch (Exception e) { e.printStackTrace(); } } } private static void injectEvent(Object object) { Class clazz = object.getClass(); //获取到当前页年一切办法并遍历 Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { declaredMethod.setAccessible(true); //获取办法上的一切注解并遍历 Annotation[] annotations = declaredMethod.getDeclaredAnnotations(); for (Annotation annotation : annotations) { //获取注解自身 Class annotationType = annotation.annotationType(); //获取注解上的OnEvent注解 OnEvent onEvent = annotationType.getAnnotation(OnEvent.class); if (onEvent == null) { continue; } //拿到注解中的元素 String setCommonListener = onEvent.setCommonListener(); Class commonListener = onEvent.commonListener(); try { //由于上边没有明白获取是哪个注解,所以这里需求运用反射获取viewId Method valueMethod = annotationType.getDeclaredMethod("value"); valueMethod.setAccessible(true); int viewId = (int) valueMethod.invoke(annotation); //经过反射findViewById获取到对应的view Method findViewByIdMethod = clazz.getMethod("findViewById", int.class); Object view = findViewByIdMethod.invoke(object, viewId); //经过反射获取到view中对应的setCommonListener办法 Method viewMethod = view.getClass().getMethod(setCommonListener, commonListener); //运用动态代理监听回调 Object proxy = Proxy.newProxyInstance( clazz.getClassLoader(), new Class[]{commonListener}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //最终执行被标注的办法 return declaredMethod.invoke(object, null); } } ); //调用view的setCommonListener办法 viewMethod.invoke(view, proxy); } catch (Exception e) { e.printStackTrace(); } } } }

}
复制代码
运用
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
@BindView(R.id.button1) private Button button1; @BindView(R.id.button2) Button button2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MsInjector.inject(this); } @OnClick(R.id.button1) public void clickButton1() { Toast.makeText(this, "click button1", Toast.LENGTH_SHORT).show(); } @OnClick(R.id.button2) public void clickButton2() { Toast.makeText(this, "click button2", Toast.LENGTH_SHORT).show(); } @OnLongClick(R.id.button1) public boolean longClickButton1() { Toast.makeText(this, "long click button1", Toast.LENGTH_SHORT).show(); return false; } @OnLongClick(R.id.button2) public boolean longClickButton2() { Toast.makeText(this, "long click button2", Toast.LENGTH_SHORT).show(); return false; }

}

    推荐阅读