安卓进阶之自己实现 ViewInject框架
来源:互联网 发布:防御sql注入原理 编辑:程序博客网 时间:2024/05/17 02:58
以前做web开发的时候经常用得到的就是SSH框架,即struts2、spring、hibernate三大框架,他们分别负责了不同的层的业务逻辑,其中spring框架是我觉得最猛的一个框架,它几乎贯穿到整个web开发中,而它的特色功能就是IOC、AOP等,AOP是面向切面编程,根据动态代理技术来动态管理我们的java代码,功能非常强大。IOC是控制反转,为什么叫控制反转呢?因为我们一般实例化一个对象都是自己手动通过new来实现,而spring通过自己的IOC技术就可以通过配置或者注解的方法来帮助我们new一个对象,使我们不用关注实例化对象的方法,从而注重程序的业务逻辑,在一方面也能达到很好的解耦作用。
现在安卓中也引入了IOC技术,可以在网上下载到ViewInject项目来使用我们的IOC功能,于是我们又多了一个新技能,使用别人写的ViewInject框架。程序员中有一句话叫做不要重复的制造轮子,我们大多数程序员都是拿来主义,只要功能实现就行,而不去管其中的原理,不自己是考虑一下怎么实现的,但叫自己做的话能不能实现呢?于是我决定动手实现ViewInject框架,虽然比较简陋,但是自己的东西写出来才是硬道理哇。
要实现ViewInject框架需要了解一下java中反射的概念,所谓反射其实就是通过非new的方式来获取我们的属性、方法等内容,同时也可以通过反射来实例化一个对象,功能非常强大,是设计框架的必备良药。通过几个例子来说明:
//有一个A类,我们传统的可以通过new A来获取对象,并且调用里面的方法或者属性//主要有一个name属性,它是私有的,如果通过new的方法还能调用吗?class A { private int age = 100; private String name = "私有属性"; public void sayHellow() { System.out.println("你好"); }}//如果需要调用里面的私有属性或者私有方法,则需要通过法神来实现:public static void main(String[] args) throws Exception { Class<A> clazz = A.class; // 实例化一个A对象 A a = clazz.newInstance(); // 获取所有的属性(包括私有属性),也可以使用getFields方法,但是这样不能 // 获取到私有属性 Field[] fileds = clazz.getDeclaredFields(); for (Field f : fileds) { // 如果需要访问私有属性,这里必须要设置为true f.setAccessible(true); System.out.println(f.get(a)); } // 获取所有的方法(包括私有方法),也可以使用getMethods方法,但是这样不能 // 获取到私有方法 Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { // 如果需要访问私有方法,这里必须要设置为true m.setAccessible(true); m.invoke(a, null); } } 打印结果: 100 私有属性 你好
可以看到通过反射能够正常访问私有属性,私有方法等,非常厉害!
我们在整合SSH框架的时候有时候为了简化经常使用注解的方式,注解英文名幼教Annotation,非常好用,用法也很简单,这里略过。。。
下面就是实现自己的ViewInject框架了
首先看一下我们使用自己的框架的代码:
@ContentView(R.layout.activity_main)//这里使用了注解public class MainActivity extends Activity { @ViewInject(R.id.tv1)//这里使用了注解 private TextView tv; @ViewInject(R.id.btn1)//这里使用了注解 private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewUtil.inject(this);//自定义的工具类 tv.setText("通过自定义矿建实现的"); } @OnClick({ R.id.btn1, R.id.btn2 })//这里使用了注解 public void btn(View view) { switch (view.getId()) { case R.id.btn1: Toast.makeText(getApplicationContext(), "点击了按钮1", Toast.LENGTH_SHORT).show(); break; case R.id.btn2: Toast.makeText(getApplicationContext(), "点击了按钮2", Toast.LENGTH_SHORT).show(); break; } }}
可以看到我们总共有三个注解类型:ContentView、ViewInject、OnClick以及一个ViewUtil工具类
首先定义自己的ContentView注解类型:
//运行环境,此处是运行时@Retention(RetentionPolicy.RUNTIME)// 此处表示注解可以存放的位置,此处设置为在类上@Target(ElementType.TYPE)public @interface ContentView { int value();}
定义ViewInject类型:
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ViewInject { int value();}
定义OnClick类型:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface OnClick { //此处返回一个数据表示可以通过定义多个 int[] value();}
最后使我们的核心控制类:
/** * 核心控制类 * * @author leilu * */public class ViewUtil { /** * 开始注解 * * @param activity */ public static void inject(Activity activity) { // 判断对应的Activity上面是否使用了ContentView注解 if (activity.getClass().isAnnotationPresent(ContentView.class)) { // 如果加了注解则转换为ContentView注解 ContentView contentView = activity.getClass().getAnnotation( ContentView.class); int layoutResID = contentView.value();// 获取布局的资源id activity.setContentView(layoutResID);// 设置布局内容 findView(activity);// 绑定view registEvent(activity);// 注册点击事件 } } /** * 注册点击事件 * * @param activity */ private static void registEvent(final Activity activity) { // 获取所有的方法 Method[] method = activity.getClass().getMethods(); for (final Method m : method) { // 判断方法上面使用存在OnClick注解 if (m.isAnnotationPresent(OnClick.class)) { // 如果存在则转换 OnClick on = m.getAnnotation(OnClick.class); int[] values = on.value();// 获取需要绑定点击事件的控件id for (int i = 0; i < values.length; i++) { final View view = activity.findViewById(values[i]); // 给其设置点击事件 view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { m.invoke(activity, view);// 调用activity里面的方法 } catch (Exception e) { e.printStackTrace(); } } }); } } } } /** * 绑定view控件 * * @param activity */ private static void findView(Activity activity) { // 获取所有属性 Field[] fields = activity.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); // 判断属性上面是否存在ViewInject注解 if (field.isAnnotationPresent(ViewInject.class)) { ViewInject vi = field.getAnnotation(ViewInject.class); int resourceId = vi.value();// 获取控件资源id try { field.set(activity, activity.findViewById(resourceId));// 绑定控件 } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }}
OK,自定义框架实现完毕!看看效果:
- 安卓进阶之自己实现 ViewInject框架
- Android 进阶 Android 中的 IOC 框架 【ViewInject】
- 【Java进阶】实现自己的ORM框架
- Android快速开发框架之xUtils---注解模块 ---- ViewInject
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
- ios ASIHttpQuenue 队列
- 关于URL和URI在Android中的拓展
- 晒一下我的智能小车,留作纪念
- 两个Android开源项目:Android显示GIF动画
- 浅谈单片机以太网接入方案
- 安卓进阶之自己实现 ViewInject框架
- 实现页面的div小提示层
- linux 环境变量设置方法总结(PATH/LD_LIBRARY_PATH)
- pid相关命令
- hive启动报错 java.net.URISyntaxException: Relative path in absolute URI: ${system:java.io.tmpdir%7D/$%7B
- SSDB 安装 和 特性介绍
- 态度
- Linux 中的零拷贝技术,第 2 部分
- 根据经纬度查询附近的点