XUtils 简单实现
来源:互联网 发布:ubuntu安装libapu 编辑:程序博客网 时间:2024/06/05 07:05
XUtils是一个很强大的框架,几乎涵盖了我们一个App常用的功能,它包含四部分
一.DBUtils:数据库操作
二.ViewUtils:通过注解的方式进行UI绑定,资源和事件绑定
三.HttpUtils:网络连接,同步异步,上传下载 都涵盖
四.BitmapUtils:加载本地/网络图片,解决了滑动时图片错位的问题,以及图片的内存管理
git项目地址:https://github.com/wyouflf/xUtils
今天这篇文章主要是为了记录下,xUtils中ViewUtils的实现思路。当然原框架是很强大的,这里只是简单实现,希望能给学习XUtils的人一些帮助
ViewUtils进行布局的绑定和资源的初始化,事件的绑定主要是通过注解+反射的方式实现的,主要的类如下(图画的丑见谅)
简单说下java的元注解,它的作用主要是注解其他注解,java5.0定义了4个meta-annotation类型,他们分别是:
@Type:说明了Annotation所修饰对象的范围
@Retention:定义了Annotation保留的时长
@Document:可以被文档化,是一个标记注解,没有成员
@Inherited:标记注解,被该注解修饰的class的子类也继承该注解
@Type:
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention:
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保
(ps:ViewXutils使用的运行时的注解,所以它和knife比起来是有一定性能损耗的)
绑定布局:
1.首先定义一个接受Layout Id的Annotation
2.通过反射的方式得到setContentView 方法invoke一下即可
1.
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ContentView { int value();}
2.
public static void injectLayout(Object context) { //获取注解 //设置 Class<?> clazz = context.getClass(); ContentView hConextView = clazz.getAnnotation(ContentView.class);//获取ContextView注解 if (hConextView == null) return; //获取方法 try { Method setContentView = clazz.getMethod("setContentView", int.class); int layoutId = hConextView.value(); setContentView.invoke(context, layoutId); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
1.创建一个接受控件id的Annotation
2.获取注解 ,通过反射得到findViewById方法invoke
3.将实例化的结果绑定在控价上
1.
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ViewInject { int value();}
2,3
public static void injectView(Object context) { //1.获取有注解的字段 //2.初始化 //3.绑定 try { Class<?> clazz = context.getClass();// Field[] fields = clazz.getFields();//获取所有公共的字段 Field[] fields = clazz.getDeclaredFields();//获取所有申明的字段 Method findViewById = clazz.getMethod("findViewById", int.class); for (Field field : fields) { //拿到字段的注解 ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject == null) { continue; } int viewId = viewInject.value(); View view = (View) findViewById.invoke(context, viewId); //绑定 field.setAccessible(true);//设置可写 field.set(context, view); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
绑定事件:
由于安卓的绑定事件很多,我们不可能在工具类中讲每个事件都进行判断,所以我们需要定义一个包含事件的三要素的Base-Annotation,然后再定义各个具体事件的Annotation。在工具类中通过获取Base-Annotation的事件三要素进行操作
1.定义事件 Base-Annotaion
2.定义具体事件Annotation
3.获取Base-Annotation,反射出相应的控件和事件进行调用
1.
@Target(ElementType.ANNOTATION_TYPE)//注解的注解@Retention(RetentionPolicy.RUNTIME)public @interface EventBase { String listenerSetter(); Class<?> listenerType(); String callbackMothod();}
2.
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@EventBase(listenerSetter = "setOnClickListener", listenerType = View.OnClickListener.class, callbackMothod = "onClick")public @interface OnClick { int[] value() default -1;}
3.
public static void injectEvent(Object context) { //1.获取方法 //2.获取注解 //3.获取注解的注解 //4.根据注解设置相应的事件 Class<?> classzz = context.getClass(); //1 Method[] methods = classzz.getDeclaredMethods(); for (Method method : methods) { //2 Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { //3// EventBase eventBase = annotation.getClass().getAnnotation(EventBase.class);//错误 Class<?> annotationsType = annotation.annotationType(); EventBase eventBase = annotationsType.getAnnotation(EventBase.class); if (eventBase == null) { continue; } //获取三要素 String listenerSetter = eventBase.listenerSetter(); Class<?> listenerType = eventBase.listenerType(); String callBack = eventBase.callbackMothod(); //获取控件 //因为我不知道传入的是什么类型的注解,所以通过反射获取到里面的方法 try { Method value = annotation.getClass().getMethod("value"); int[] viewId = (int[]) value.invoke(annotation); Method findViewById = classzz.getMethod("findViewById", int.class); for (int id : viewId) { View view = (View) findViewById.invoke(context, id); if(view==null) continue; //找到需要设置的方法 Method setListenerMethod = view.getClass().getMethod(listenerSetter, listenerType); //将这个注解代表的方法设置给这个控件 ListenerInvocation invocation = new ListenerInvocation(context, method); Object listenerTypeInstance = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class<?>[]{listenerType}, invocation); //设置方法 setListenerMethod.invoke(view, listenerTypeInstance); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } }
ListenerInvocation:
代码地址:点击打开链接public class ListenerInvocation implements InvocationHandler { private Object holdObject;//方法的持有对象 private Method method;//调用方法 public ListenerInvocation(Object holdObject, Method method) { this.holdObject = holdObject; this.method = method; } @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { return this.method.invoke(holdObject, objects);// return null; }}
- XUtils 简单实现
- Android-使用xUtils实现简单断点续传(主要代码)
- 简单使用xUtils-HttpUtils
- XUtils简单入门使用
- xUtils的简单使用
- XUtils的简单使用
- Xutils的简单总结
- xUtils的简单使用
- Xutils简单介绍
- XUtils数据库的简单使用;
- xutils 3的简单使用
- 断点续传简单练习(xutils)
- Android中如何利用xUtils简单快捷的实现文件下载
- RecyclerView简单解析使用Xutils实现表格效果和普通listview效果
- 借助Xutils实现多线程下载
- xUtils工具实现下载功能
- 使用xutils实现多线程下载
- XUtils的BitmapUtils实现分析:
- 【智能医疗】人工智能+医疗为何备受资本青睐?这三大场景将先行落地
- 启动tomcat 报错ASM ClassReader failed to parse class file
- 9.Python入门之递归
- 替换为右侧最大值-LintCode
- 解决Chrome不支持NPAPI插件的方法(贴吧旺旺等)
- XUtils 简单实现
- java 多线程之内存可见性
- eclipse+springmvc入门小例子
- mybatis多参数传入的动态sql
- 算法题练习系列之(四十四):NowCoder小定律
- 电子商务复习笔记六:数据挖掘概述
- Linux进程间通信——使用信号
- Angular4学习笔记(四)
- 使用IntelliJ IDEA 配置Maven(入门)