效果

每次新建页面控件的findViewById是每个android开发者的痛苦。在这方面已经有很多第三方框架帮我们解放了双手,这次就是利用注解来解决findViewById。

public class ObserverActivity extends AppCompatActivity{    @ViewInject(R.id.activity_btn)    Button button;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_observer);        AnnotateUtils.injectViews(this);        button.setText("newText");    }}

一、实现原理

在Java中,通过反射,我们可以获取每一个类的详细信息,比如有什么属性字段,有什么方法,类名等,我们通过注解和反射配合,使用反射调用类中的属性,然后读取注解的参数来进行属性的赋值。简单的说,就是其实我们还是会调用findViewById这个方法,但是,这个方法可以放到工具类中执行了,我们只需要像上面那样给出参数就行了。这个形式就和注解框架ButterKnife一样

二、创建自定义注解

新建一个注解。

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ViewInject {    int value();}

其中@Target的意思是我们注解的目标,这里是ElementType.FIELD,也就是作用于属性的。
它的类型有以下几种:
- 1.CONSTRUCTOR:用于描述构造器
- 2.FIELD:用于描述字段
- 3.LOCAL_VARIABLE:用于描述局部变量
- 4.METHOD:用于描述方法
- 5.PACKAGE:用于描述包
- 6.PARAMETER:用于描述参数
- 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

然后@Retention的意思是注解的运行级别
它的类型有以下几种
- 1.SOURCE:在源文件中有效(即源文件保留)
- 2.CLASS:在class文件中有效(即class保留)
- 3.RUNTIME:在运行时有效(即运行时保留)

三、注入注解的工具类

public class AnnotateUtils {    public static void injectViews(Activity activity) {        // 获取activity的Class        Class<? extends Activity> object = activity.getClass();        // 通过Class获取activity的所有属性        Field[] fields = object.getDeclaredFields();        for (Field field : fields) {            // 获取字段的注解,如果没有ViewInject注解,则返回null            ViewInject viewInject = field.getAnnotation(ViewInject.class);            if (viewInject != null) {                // 获取属性的注解的参数,这就是控件的id                int viewId = viewInject.value();                try {                    // 获取类中的findViewById方法,参数为int                    Method method = object.getMethod("findViewById", int.class);                    // 执行该方法,返回一个Object类型的View实例                    Object resView = method.invoke(activity, viewId);                    field.setAccessible(true);                    // 把属性的值设置为该View的实例                    field.set(activity, resView);                } catch (NoSuchMethodException e) {                    e.printStackTrace();                } catch (IllegalAccessException e) {                    e.printStackTrace();                } catch (InvocationTargetException e) {                    e.printStackTrace();                }            }        }    }}

主要思路:
获取activity的所有的Filed数组,然后遍历它们,检验有自定义注解ViewInfect的属性。
然后获取注解的参数Id,通过反射调用findViewById来获取指定View给该属性赋值。

这样就可以做到ButterKnife一样的效果了。

更多相关文章

  1. Android系统属性SystemProperties分析
  2. GridView 中Item项居中显示
  3. Android(安卓)横竖屏的锁定
  4. Android(安卓)清单文件属性大全
  5. android selector下的设置背景属性值
  6. android的edittext怎么设置不默认被选中
  7. 2011.08.15——— android audioManager 获取音量
  8. android 动画
  9. Android(安卓)兼容获取Mac地址与手机信息工具

随机推荐

  1. eclipse android安装
  2. android framework 层服务 分析
  3. Android开发之GridView属性介绍
  4. mac 安装Android studio遇到的问题及解决
  5. Android设备管理器漏洞
  6. Android(安卓)水波效果原理与实现
  7. 后台动态添加布局文件、控件与动态设置属
  8. Android调用系统摄像头拍照并剪裁压缩
  9. android 中文 api (43) —— Chronometer
  10. Android studio 无法启动安卓模拟器