自己动手写一个简单的IOC框架,使用注解绑定资源和事件
程序员都是懒惰的;事实证明,懒人才能改变世界、创造未来。
几行代码就能搞定的一个简单IOC框架,使用方式如下:
public class MainActivity extends AppCompatActivity {
/**
* 属性注解
*/
@ViewInject(R.id.tv)
TextView mTv;
@ViewInject(R.id.btn)
Button mBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注入
ViewUtils.inject(this);
mTv.setText("You need 安慰");
}
/**
* 方法注解
* @param view
*/
@ViewClick({R.id.btn,R.id.tv})
private void click(View view) {
Toast.makeText(this, view.getId() + "", Toast.LENGTH_SHORT).show();
}
}
庖丁解牛
需要使用@interface申明注解类,主要使用的注解有:
@Retention :
申明注解生效的时期,可以选择三个参数:SOURCE、CLASS、RUNTIME。
SOURCE:Annotation is only available in the source code.
CLASS:Annotation is available in the source code and in the class file, but not at runtime. This is the default policy.
RUNTIME:Annotation is available in the source code, the class file and is available at runtime.
因为我们是在运行时对注解进行反射操作,所以这里我们选择 RUNTIME。
@Target :
申明注解在哪些成员上可用,不申明默认全部可用,常用可选择的有:TYPE、FIELD、METHOD、CONSTRUCTOR等
对具体的类进行分析
- ViewInject 注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewInject {
/**
* 注解参数名和参数类型
*/
int value();
}
- ViewClick 注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ViewClick {
/**
* 可以同时绑定多个View的点击事件
*/
int[] value();
}
- ViewUtils 工具类
public class ViewUtils {
/**
* 执行注入操作
*
* @param activity
*/
public static void inject(final Activity activity) {
/**
* 使用getDeclaredFields()可以获取到类中所有的Filed,包括私有的。
*/
Field[] fields = activity.getClass().getDeclaredFields();
//遍历Fields
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
//设置私有的也能访问到
field.setAccessible(true);
//获取指定注解对象
ViewInject annotation = field.getAnnotation(ViewInject.class);
//如果该Filed上有这个注解
if (annotation != null) {
//获取注解的值
int id = annotation.value();
View view = activity.findViewById(id);
try {
// 给activity中的view设值
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 给View设置点击监听事件
* 使用getDeclaredMethods()可以获取到类中所有的Method,包括私有的。
*/
Method[] methods = activity.getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
final Method method = methods[i];
method.setAccessible(true);
ViewClick annotation = method.getAnnotation(ViewClick.class);
if (annotation != null) {
// 这是个int[]形式,可能有多个值
int[] ids = annotation.value();
for (int j = 0; j < ids.length; j++) {
// 更具获取到的id 去设置点击监听事件
final View button = activity.findViewById(ids[j]);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// 调用指定方法
method.invoke(activity, button);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
总结
简单的使用注解和反射就完成一个简单IOC框架,可以减少很多findViewById的代码呢。