在一次封装项目的过程,偶然发现一种基于反射的全自动findViewById方式。废话不先说,先来看看如何使用:
、
什么?就没了?
是的,没错,就这么简单!
只要声明成员变量后,无需其他任何额外操作(不需要注解,不需要绑定,不需要插件生成)即可自动寻找控件。
唯一的要求是:你需要布局文件中控件id与java代码中的变量名保持一致。因为该方法是通过反射遍历所有变量的方式实现的。
以下上代码
//自动findViewById(必须保证布局文件中的id与变量名一致)
private void autoFindView() {
Class mClass = this.getClass();
while (true)
{
Field[] fields = mClass.getDeclaredFields();
for (Field field : fields)
{
if (View.class.isAssignableFrom(field.getType()))
{
String fieldName = field.getName();
View view = findViewById(getResources().getIdentifier(fieldName, "id", getPackageName()));
if (view != null)
{
field.setAccessible(true);
try {
field.set(this,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
mClass = mClass.getSuperclass();
//tip:可修改Activity.class.getName()以重新指定搜寻父类上限
if (mClass.getName().equals(Activity.class.getName()))
break;
}
}
然后把这个方法放在您的BaseActivity中,重写setContentView并在父类之后调用即可,是不是无脑又方便?
注意:
- 布局文件中的id与变量名必须一致,这个强调了很多次,一定要注意;
- 仅仅对根布局以下的控件有效,对于使用inflate构造出来的布局,以及类似于NavigationView的HeadView无效。这是因为findViewById方法局限性,有更好解决思路可以联系我;
- 考虑到BaseAcivity中会封装常用的控件,该方法会遍历当前类及所有父类的成员变量,如果您继承了第三方Activity,为了性能优化请参考代码中tip部分的注释;