Xutils中注解的应用
注解入门(一)中,基本介绍了注解的简单定义,元注解各个参数的的意义及注解的简单应用。在这里我们通过分析xutils开源框架的源码,进一步理解注解。我们只取其中view模块来分析。view模块主要是用完注解方式就进行UI,资源和事件绑定,避免了繁琐的findByViewId()和一些事件的接口的实现。
注解定义:ContentView
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value(); //view的id
}
注解定义:ViewInject
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value();
/* parent view id */
int parentId() default 0;
}
inject view: 解析控件属性注解
//通过反射获得控件属性
Field[] fields = handlerType.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
Class<?> fieldType = field.getType();
if (
/* 不注入静态字段 */ Modifier.isStatic(field.getModifiers()) ||
/* 不注入final字段 */ Modifier.isFinal(field.getModifiers()) ||
/* 不注入基本类型字段 */ fieldType.isPrimitive() ||
/* 不注入数组类型字段 */ fieldType.isArray()) {
continue;
}
//遍历属性,获得属性的注解
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
try {
//如果属性上有注解,根据注解的值对应的id在资源中寻找view,并创建view对象
View view = finder.findViewById(viewInject.value(), viewInject.parentId());
if (view != null) {
//如果view不为空,说明注解的值对应的view存在,将其赋给当前遍历的属性
field.setAccessible(true);
field.set(handler, view);
} else {
throw new RuntimeException("Invalid @ViewInject for "
+ handlerType.getSimpleName() + "." + field.getName());
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
}
} // end inject view
注解定义:Event
/**
* 事件注解.
* 被注解的方法必须具备以下形式:
* 1. private 修饰
* 2. 返回值类型没有要求
* 3. 参数签名和type的接口要求的参数签名一致.
* Author: wyouflf
* Date: 13-9-9
* Time: 下午12:43
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Event {
// 控件的id集合, id小于1时不执行ui事件绑定.
int[] value();
//控件的parent控件的id集合, 组合为(value[i], parentId[i] or 0).
int[] parentId() default 0;
//事件的listener, 默认为点击事件.
Class<?> type() default View.OnClickListener.class;
// 事件的setter方法名, 默认为set+type#simpleName.
String setter() default "";
String method() default "";
}
inject event:解析view事件注解
//通过反射获得所有方法
Method[] methods = handlerType.getDeclaredMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
if (Modifier.isStatic(method.getModifiers())
|| !Modifier.isPrivate(method.getModifiers())) {
continue;
}
//检查当前方法是否是event注解的方法
Event event = method.getAnnotation(Event.class);
if (event != null) {
try {
// id参数
int[] values = event.value();
int[] parentIds = event.parentId();
int parentIdsLen = parentIds == null ? 0 : parentIds.length;
//循环所有id,生成ViewInfo并添加代理反射
for (int i = 0; i < values.length; i++) {
int value = values[i];
if (value > 0) {
ViewInfo info = new ViewInfo();
info.value = value;
info.parentId = parentIdsLen > i ? parentIds[i] : 0;
method.setAccessible(true);
EventListenerManager.addEventMethod(finder, info, event, handler, method);
}
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
}
} // end inject event
使用Xutils3:
使用xUtils的第一步就是必须创建自己的Application类:
public class MyApplication extends Application {
@Override
publicvoidonCreate() {
super.onCreate();
x.Ext.init(this);//Xutils初始化
}
在AndroidManifest.xml的application标签中添加如下代码:
android:name=”.Mypplication”
@ContentView(R.layout.activity_main)
public class MainActivity extends Activity {
// 使用ViewUtils绑定控件
@ViewInject(R.id.btn1)
private Button btn1;
@ViewInject(R.id.btn2)
private Button btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
x.view().inject(this);
}
//支持绑定点击事件
@Event(value = R.id.btn1,
type = View.OnClickListener.class
/*可选参数, 默 认是View.OnClickListener.class*/)
public void btnOnClick(View v){
}
}
注意:
使用记得加上权限:
1.android.permission.WRITE_EXTERNAL_STORAGE
2. android.permission.INTERNET