Android UI IoC注解加载控件
知识点:注解 反射
1. 业务Activity 和注解 InjectView
// 普通页面Activity代码,正常启动即可正常加载ioc_act.xml
@ContentView(R.layout.ioc_act)
public class IocAct extends BaseActivity {
@InjectView(R.id.tv)
private TextView tv;
@Override
protected void onResume() {
super.onResume();
// 也是通过注解加载tv(类ButterKnife原理)
// TextView tv = findViewById(R.id.tv);
Toast.makeText(this, tv.getText().toString(), Toast.LENGTH_SHORT)
.show();
}
}
// 该注解作用于属性
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
int value();
}
2. 业务ioc_act.xml ,BaseActivity.java实现同上篇
3. InjectManager实现控件注入
public class InjectManager {
public static void inject(Activity activity) {
// 布局的注入
injectLayout(activity);
// 控件的注入
injectViews(activity);
}
// 布局的注入
private static void injectLayout(Activity activity) {
......
}
// 控件的注入
private static void injectViews(Activity act) {
// 获取类
Class<? extends Activity> clazz = act.getClass();
// 获取类的所有属性
Field[] fields = clazz.getDeclaredFields();
// 循环每个属性
for (Field field : fields) {
// 获得属性上的注解
InjectView injectView = field.getAnnotation(InjectView.class);
// 获取注解的值
if (injectView != null) { // 并不是所有的属性都有注解
int viewId = injectView.value();
// 获取findViewById方法,并执行
try {
Method method = clazz.getMethod("findViewById", int.class);
Object view = method.invoke(act, viewId);
// 另一种写法:
// view = activity.findViewById(viewId);
// 设置访问权限private
field.setAccessible(true);
field.set(act, view); // 属性的值赋给控件,在当前Activity
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
概括:其实上面几步就是ButterKnife的实现原理,免去大量findViewById之类的代码