之前的一篇文章介绍了什么是注解 (直达链接:点击打开链接)
现在有许多开源的注解框架,比如:butterknife/androidannotation等,这些框架能帮助我们大大简化了代码,使我们不用再机械的写这种findViewById, setOnClickListener等方法
接下来就自己用注解,实现了一下view的绑定
1.声明注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface EActivity {
int value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ViewById {
int value();
}
2.在activity中使用注解
@EActivity(R.layout.activity_annotation) //绑定布局文件
public class AnnotationActivity extends AppCompatActivity implements View.OnClickListener {
@ViewById(R.id.text)
private TextView mTextView;
@ViewById(R.id.button)
private Button mButton;
private int mClickTimes = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用注解工具类实现对view的绑定
AndroidBindViewUtils.startBinding(this);
mButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
mClickTimes++;
mTextView.setText("点击了btn " + mClickTimes + " 次!");
break;
}
}
}
3.如何实现view的绑定
这里用的是运行时注解,需要借助反射的方式获取到具体的方法,然后和对应的值进行绑定
public class AndroidBindViewUtils {
private static Method sMethodSetContentView;
private static Method sMethodFindViewById;
public static void startBinding(Activity activity) {
bindContentView(activity);
bindViewById(activity);
}
private static void bindContentView(Activity activity) {
EActivity eActivity = activity.getClass().getAnnotation(EActivity.class);
if (eActivity != null) {
int contentviewId = eActivity.value(); //拿到绑定的layout id
if (sMethodSetContentView == null) {
getSetContentViewMethod();
}
try {
sMethodSetContentView.invoke(activity, contentviewId); //通过反射调用activity的setContentView方法
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
private static void bindViewById(Activity activity) {
Field[] fields = activity.getClass().getDeclaredFields();//拿到activity的所有变量
for (Field field : fields) {
ViewById viewById = field.getAnnotation(ViewById.class);//通过变量拿到ViewById注解
if (viewById != null) {
int id = viewById.value();//拿到具体的view id
try {
if (sMethodFindViewById == null) {
getFindViewByIdMethod();
}
Object view = sMethodFindViewById.invoke(activity, id); //通过反射findViewById获取具体的view
field.setAccessible(true);
field.set(activity, view);//把这个view赋值给field变量
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
private static void getSetContentViewMethod() {
if (sMethodSetContentView == null) {
try {
sMethodSetContentView = Activity.class.getDeclaredMethod("setContentView", int.class);
sMethodSetContentView.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
private static void getFindViewByIdMethod() {
if (sMethodFindViewById == null) {
try {
sMethodFindViewById = Activity.class.getDeclaredMethod("findViewById", int.class);
sMethodFindViewById.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}