Android UI IoC注解加载布局
知识点:注解 反射
接下来一步步实现
1. 业务Activity 和 注解类ContentView
// 普通页面Activity代码,正常启动即可正常加载ioc_act.xml
@ContentView(R.layout.ioc_act)
public class IocAct extends BaseActivity {
}
// 该注解作用于类,接口或者枚举类型上
@Target(ElementType.TYPE)
// 注解会在class字节码文件中存在,jvm加载时可以通过反射获取到该注解的内容
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
// int类型布局
int value();
}
2. 业务ioc_act.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注解加载布局" />
</RelativeLayout>
3. BaseActivity.java实现
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 帮助子类进行,布局、控件、事件的注入
// 本篇先讲布局注入,后续控件,事件在补上
InjectManager.inject(this);
}
}
4. InjectManager实现
public class InjectManager {
public static void inject(Activity act) {
// 布局的注入
injectLayout(act);
}
private static void injectLayout(Activity act) {
Class<? extends Activity> clazz = act.getClass();
// 获取类的注解
ContentView contentView = clazz.getAnnotation(ContentView.class);
if (contentView != null) {
int layoutId = contentView.value();
// 获取Activity指定方法
try {
Method method = clazz.getMethod("setContentView", int.class);
method.invoke(act, layoutId);
// 另一种写法:
// act.setContentView(layoutId);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
基于上述4步概括一下:
- 首先IocAct 继承 BaseActivity,BaseActivity在onCrate方法中通过InjectManager的inject方法代替完成了setContentView(R.layout.ioc_act)加载布局的操作
- InjectManager的inject方法首先获取IocAct的注解,继而获取注解值(R.layout.ioc_act),然后通过java反射获取Activity的setContentView方法调用,实现加载布局的任务
实际开发场景下,我们没必要这么去做,这么做目的是为了熟悉对注解,反射的使用