Android开发 打造自己的Annotation框架
最近在回顾注解和反射方面的知识。
之前在项目开发过程中,也曾经体验过ButterKnife的注解,想结合反射和注解自己写一个框架。结合着大牛的博客,和自己的理解。实现了Activity加载layout和view初始化的注解。
一.原理
package csu.lzw.reviewandroid.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Created by Allen_Binan on 2016/4/2.*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LBindView {int id() default -1;
}
@Target用来表示这个注解修饰的对象是什么,FIELD表示是成员变量,例如Actvity当中的View控件。
@Retentiong表示这个注解是在什么级别保存信息。RUNTIME表示是运行时。
@interface是用于自定义注解的,它里面定义的方法的声明不能有参数,也不能抛出异常,并且方法的返回值被限制为简单类型、String、Class、emnus、@interface,和这些类型的数组。
注解@Target也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,值为:ANNOTATION_TYPE,CONSTRUCTOR ,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER和TYPE,如@Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。
@RetentionRetention注解表示需要在什么级别保存该注释信息,用于描述注解的生命周期,它有一个RetentionPolicy类型的value,是一个枚举类型,它有以下的几个值:
1.用@Retention(RetentionPolicy.SOURCE)修饰的注解,指定注解只保留在源文件当中,编译成类文件后就把注解去掉;
2.用@Retention(RetentionPolicy.CLASS)修饰的注解,指定注解只保留在源文件和编译后的class 文件中,当jvm加载类时就把注解去掉;
3.用@Retention(RetentionPolicy.RUNTIME )修饰的注解,指定注解可以保留在jvm中,这样就可以使用反射获取信息了。
默认是RUNTIME,这样我们才能在运行的时候通过反射获取并做对应的逻辑处理。
同理可得,用于修饰Activity类,而加载layout布局的注解。
package csu.lzw.reviewandroid.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Created by Allen_Binan on 2016/4/2.*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface LBindContentView {int layoutId() default -1;
}
最终,在Activity中实现的效果如下
package csu.lzw.reviewandroid;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;import csu.lzw.reviewandroid.annotation.LBindContentView;
import csu.lzw.reviewandroid.annotation.LBindView;
import csu.lzw.reviewandroid.annotation.LViewBindUtils;@LBindContentView(layoutId = R.layout.activity_main)
public class MainActivity extends AppCompatActivity {private static final String TAG="MainActivity";@LBindView(id=R.id.toggleButton)private Button tg;@LBindView(id = R.id.toggleButton2)private Button tg2;@LBindView(id = R.id.toggleButton3)private Button tg3;@LBindView(id = R.id.toggleButton4)private Button tg4;@LBindView(id = R.id.toggleButton5)private Button tg5;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);LViewBindUtils.inject(this);tg.setText("test");tg2.setText("test2");}}
关键的实现在于这一步
LViewBindUtils.inject(this);
这一步里做了什么呢
对于初始化view的注解,那么获取this指向的Activity中的成员,检查成员中是否有自定义的注解,如果有的话,获取注解中声明的id,使用反射,获取Activity的findviewbyid方法,使用invode调用,并将返回值通过反射赋值给将要初始化的view.
对于加载Activity布局的view,类似地,检查activity类上有没有自定义的注解,如果有的话,通过反射,调用setcontentview.
package csu.lzw.reviewandroid.annotation;import java.lang.reflect.Field;
import java.lang.reflect.Method;import android.app.Activity;
import android.util.Log;public class LViewBindUtils
{private static final String METHOD_SET_CONTENTVIEW = "setContentView";private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";public static void inject(Activity activity){injectContentView(activity);injectViews(activity);// injectEvents(activity);}/*** 注入所有的view控件* * @param activity*/private static void injectViews(Activity activity){Class<? extends Activity> clazz = activity.getClass();Field[] fields = clazz.getDeclaredFields();// 遍历所有成员变量for (Field field : fields){LBindView viewInjectAnnotation = field.getAnnotation(LBindView.class);if (viewInjectAnnotation != null){int viewId = viewInjectAnnotation.id();if (viewId != -1){// 初始化Viewtry{Method method = clazz.getMethod(METHOD_FIND_VIEW_BY_ID,int.class);Object resView = method.invoke(activity, viewId);field.setAccessible(true);field.set(activity, resView);} catch (Exception e){e.printStackTrace();}}}}}/*** 注入主布局文件* * @param activity*/private static void injectContentView(Activity activity){Class<? extends Activity> clazz = activity.getClass();// 查询类上是否存在ContentView注解LBindContentView contentView = clazz.getAnnotation(LBindContentView.class);if (contentView != null)// 存在{int contentViewLayoutId = contentView.layoutId();try{Method method = clazz.getMethod(METHOD_SET_CONTENTVIEW,int.class);method.setAccessible(true);method.invoke(activity, contentViewLayoutId);} catch (Exception e){e.printStackTrace();}}}
}
Android开发 打造自己的Annotation框架相关推荐
- 移动周刊第 182 期:谈 Android 开发技巧、 iOS 系统框架实践
写在前面 移动周刊第 182 期如约而至.如果你有好的文章以及优化建议,请发送邮件至mobilehub@csdn.net,在技术探索的道路上我们共同进步. YouTube 推出 VR 视频和 360 ...
- Android开发使用的常见第三方框架汇总
1.volley 项目地址 https://github.com/smanikandan14/Volley-demo (1) JSON,图像等的异步下载: (2) 网络请求的排序(schedu ...
- Android开发中用到的第三方框架汇总
最近上网搜索了一些框架资料,整理了以下常用框架,希望在项目中有所帮助. 1.网络请求框架 android-async-http 该网络框架的介绍文章地址:http://www.cnblogs.com/ ...
- 云炬Android开发笔记 5-1,2网络框架接口创建
1.网络框架接口创建 1.1 使用的是第三方的框架 [第三方框架]Retrofit,封装一个通用的框架,可以使用RxJava和RxAndroid进行封装,比较难,这里不做讲解: 1.2 restful ...
- Android 开发的两种框架 MVC和MVP 的简单分析
在常见的android开发框架,有MVC和MVP两种,下面我来分别简单介绍一下. 一.MVC框架 MVC,即model(模型),view(视图),controler(控制器)三个单词的简称. 其中Mo ...
- Android开发指南中文版
Android开发指南中文版 -应用程序框架 iefreer@hotmail.com 2009/9/10 个人主页: http://blog.csdn.net/iefreer 本文是对Androi ...
- Android开发软件架构思考以及经验总结
欢迎关注我的知乎:井方哥 前言 架构设计,到底是什么呢?基于这段时间的学习和自己的一些思考,我认为架构是基于产品和技术所达成的一种共识.我不是专业的架构师,也不是经验老道的开发者.本文目的有三,一是整 ...
- Android 开发软件架构思考以及经验总结
原文地址:http://blog.csdn.net/jf_1994/article/details/53870534 前言 架构设计,到底是什么呢?基于这段时间的学习和自己的一些思考,我认为架构是基于 ...
- Android开发-小技巧汇总2
启动虚拟机时,在 launch options 窗口中 有个 wipe user data ,勾选它,将会让虚拟机 [恢复出厂设置] 2.[如果想让自己的应用程序有多个启动图标:] 为一个应用的 多个 ...
最新文章
- mysql基于replication实现最简单的M-S主从复制
- windows 7 旗舰版下无法安装 msi 文件 解决办法
- linux tail 命令,Linux tail命令的巧妙应用
- hotspot 默认 gc_默认HotSpot最大直接内存大小
- python 链表倒数第k个节点_链表-删除单链表中倒数第k个节点
- python云计算开发技术_云计算开发学习笔记:Python3 面向对象技术简介
- 关闭被占用的tomcat端口
- 群辉发布RackStation系列机型——RS3621RPxs、RS3621xs+与RS4021xs+
- 如果你被这个视频深深地震撼!那你一定是幸运的!
- Boost Asio Examples(整理)
- 【轨迹跟踪】基于matlab无人机轨迹跟踪【含Matlab源码 1152期】
- 在知乎上学 Python - 入门篇
- 全国计算机技术与软件专业技术资格(水平)考试2019年上半年考试公告(湖北省)
- [EULAR文摘] 超声滑膜炎和腱鞘炎对已获临床缓解患者病情复发的预测
- 阿里巴巴集团--软件测试--《社招、校招jd、公司具体介绍,校园招聘公告,应届生招聘流程,技术培训,薪资福利》整理
- CentOS下安装MRTG
- Java实战小游戏《flapper Bird》完整版,含源码
- 【vulnhub】Raven2
- 原型图、交互设计、UI图,到底啥关系
- 土地利用现状分析(城市三维,建筑等级现状)
热门文章
- 分析:公众号运营+引流,怎么从0到1运营
- 短视频剪辑如何才能更吸引人?
- 你应该了解的工厂方法模式:优雅的代码永不过时
- Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)
- Excel学习笔记:P10-图表制作(下)
- Java练习ArrayList的运用——勇者斗史莱姆
- 单词 of 《cyberspace :if you don't love it ,leave it 》
- 小米路由硬盘版搭建ftp服务和博客
- 面向对象程序设计中对抽象的理解
- 如何将数据存入mysql_怎样将数据存入mysql数据库