自定义注解并进行动态解析
来源:互联网 发布:域名注册机构查询 编辑:程序博客网 时间:2024/06/05 01:11
尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/70230597, 本文出自:【gengqiquan的博客】
前两篇博客我们唠了Java支持基本的注解以及Android Support Annotations库提供的静态检查类型的注解
今天我们来唠唠怎么自定义动态注解,并且实现一个控件自动绑定功能(老版本butterknife,新版本改成利用IDE插件预先编译了)以及通过注解设置activity主布局,通过这两个小例子来学习如何自定义自己的动态注解
首先我们定义一个注解。还叫BindView吧
/** * Created by gengqiquan on 2017/4/18. */@Target(ElementType.FIELD)@Retention(RetentionPolicy.CLASS)@Documentedpublic @interface BindView { @IdRes int value();}
和butterknife的一样,类文件中有效,在默认方法上加上 @IdRes,防止传入非资源ID的int值。
提供一个注入器,这里我们叫MagicHand
既然是动态解析注解,那我们就需要用到反射了,通过class的
target.getDeclaredFields()
取到类下面的所有成员
然后遍历成员集合,看是否有标记了@BindView注解的成员
for (Field f : fields) { BindView bind = f.getAnnotation(BindView.class); }
若能取到注解则表明这个成员是被@BindView注解了的,通过注解的默认方法
bind.value()
取出它的值也就是资源ID
然后通过activity的
activity.getWindow().getDecorView()
方法取到顶层view,这样我们就可以通过view的
findViewById()
方法来解析ID资源对应的控件了
完整类以及方法
public class MagicHand { public static void inject(Activity activity) { Class target = activity.getClass(); Field[] fields = target.getDeclaredFields(); View decorView = activity.getWindow().getDecorView(); for (Field f : fields) { BindView bind = f.getAnnotation(BindView.class); if (bind != null) { f.setAccessible(true); try { f.set(activity, decorView.findViewById(bind.value())); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }}
切记调用field的set方法之前一定要调用f.setAccessible(true);
然后我们写一个MainActivity,在TextView上打上我们自定义的注解
在oncreate里动态注入注解,最后调用textView.setText(“你好”)看是否能正常赋值显示
public class MainActivity extends AppCompatActivity { @BindView(R.id.name) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MagicHand.inject(this); textView.setText("你好"); }}
布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Hello World!" /></RelativeLayout>
运行看下显示效果
OK,上面就是通过注解动态绑定布局的实现了
下面我们再来看看怎么通过注解设置activity主布局
定义一个布局注解
/** * Created by gengqiquan on 2017/4/18. */@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)@Documentedpublic @interface LayoutID { @LayoutRes int value();}
因为我们这个注解只作用于类,所以域我们选择了ElementType.TYPE
同时通过@LayoutRes注解限制了必须传入一个layout的资源ID
我们改变下之前的inject方法。添加一个bindContentView方法
public class MagicHand { public static void inject(Activity activity) { bindContentView(activity); bindViewAndID(activity); } private static void bindContentView(Activity activity) { Class target = activity.getClass(); LayoutID layoutID = (LayoutID) target.getAnnotation(LayoutID.class); if (layoutID != null) { activity.setContentView(layoutID.value()); } } private static void bindViewAndID(Activity activity) { Class target = activity.getClass(); Field[] fields = target.getDeclaredFields(); View decorView = activity.getWindow().getDecorView(); for (Field f : fields) { //获取字段中包含fieldMeta的注解 BindView bind = f.getAnnotation(BindView.class); if (bind != null) { f.setAccessible(true); try { f.set(activity, decorView.findViewById(bind.value())); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }}
然后在MainActivity上打上@LayoutID注解,同时去掉 setContentView(R.layout.activity_main);这一句
@LayoutID(R.layout.activity_main)public class MainActivity extends AppCompatActivity { @BindView(R.id.name) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MagicHand.inject(this); textView.setText("你好"); }}
沿用之前的布局
再次运行
发现界面显示正常。说明我们布局注入成功了
以上就是自定义注解动态解析了。由于我们是在运行时通过反射解析的。所以必然会消耗性能。后面我们再讲如何通过IDE插件进行预编译解析。
完整的示例项目GitHub地址:https://github.com/gengqiquan/MagicHand
有什么建议的可以留言喔
如果我的博客对您有帮助,请留言鼓励下或者点个赞吧!
我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。
- 自定义注解并进行动态解析
- 如何自定义注解Annotation,并利用反射进行解析
- spring扫描自定义注解并进行操作
- 自定义注解,利用反射进行解析
- Java注解教程:自定义注解示例,利用反射进行解析
- Java注解教程:自定义注解示例,利用反射进行解析
- Java注解教程:自定义注解示例,利用反射进行解析
- Java注解教程:自定义注解示例,利用反射进行解析
- Java注解:自定义注解示例,利用反射进行解析
- Java注解教程:自定义注解示例,利用反射进行解析
- SpringMVC自定义注解并自定义解析器HandlerMethodArgumentResolver
- Java自定义注解解析
- 解析动态代理模式与跟自定义注解配合使用以及事务注解原理
- java自定义注解并解读
- Java 自定义注解以及注解解析器
- Spring Aop解析自定义注解
- Java注解详解,自定义注解,利用反射解析注解
- Java注解详解,自定义注解,利用反射解析注解
- Spring Boot修改最大上传文件限制:The field file exceeds its maximum permitted size of 1048576 bytes.
- http请求重写为https要注意的问题
- 仿知乎日报2.64版本
- 微信小程序 头什么样的跳转方式 头部会有返回
- JavaComparator排序,Comparable与Comparator的区别
- 自定义注解并进行动态解析
- Arraylist类到底和泛型有什么关系呢
- iTerm一些基本命令
- spring.net与OracleODP结合时发生的版本问题
- MTK lk源码解析4( lk 阶段main.c解析)
- cifar 10 最高正确率
- myeclipse设置主题和颜色
- 攻击实例与防御
- MCU非常重要的通信接口--UART的调试