xUtils是基于Afinal开发的目前功能比较完善的一个Android开源框架,最近又发布了xUtil3.0,在增加新功能的同时又提高了框架的性能。它的功能很强大,但是有时候我们只需要其中的一些功能,如果把整个xUtils引进去没什么必要。

下面我们就讲讲如何自定义小型的xUtils,只有两个功能:通过注解找到省去findViewById()和setContentView().

一、首先:要自定义两个注解:

(1)找到activity视图的注解,即用来省去setContentView()的:

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

(2)找到控件的注解,即用来省去findViewById()的。

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

给大家解释一下,@Target ,@Retentio这种注解叫元注解。

Target的功能就是表明你这个注解是用在什么地方,它值是一个枚举类型:

 public enum ElementType {
/**
* Class, interface or enum declaration. 用于描述类、接口(包括注解类型)
*/
TYPE,
/**
* Field declaration. 字段声明
*/
FIELD,
/**
* Method declaration. 方法声明
*/
METHOD,
/**
* Parameter declaration. 参数声明
*/
PARAMETER,
/**
* Constructor declaration. 构造器声明
*/
CONSTRUCTOR,
/**
* Local variable declaration. 局部变量
*/
LOCAL_VARIABLE,
/**
* Annotation type declaration. 注释类型声明。
*/
ANNOTATION_TYPE,
/**
* Package declaration. 用于描述包
*/
PACKAGE
}

Retention大概意思是注解的生命周期什么时候生效。

public enum RetentionPolicy {
/**
* Annotation is only available in the source code. 在源文件中有效(指定注解只保留在源文件当中,
编译成类文件后就把注解去掉;)
*/
SOURCE,
/**
* Annotation is available in the source code and in the class file, but not
* at runtime. This is the default policy. 在class文件中有效,不是在运行时有效(指定注解只保留在源文件和编译后的class
文件中,当jvm加载类时就把注解去掉)
*/
CLASS,
/**
* Annotation is available in the source code, the class file and is
* available at runtime. 运行时有效
*/
RUNTIME
}

二、我们需要自定义一个工具类,这个工具类里面可以获得我们的注解,通过反射来找到我们的View。

public class InjectUtils {
public static void initContext(Object context) {
//injectLayout必须在injectView前面,因为必须先找到contentView才能够找到控件
injectLayout(context); //找到contentView
injectView(context); //找到控件
} private static void injectView(Object context) {
Class<?> clazz = context.getClass();
Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){
//获取注解
ViewInject viewInject = field.getAnnotation(ViewInject.class);
//如果上面没有标明注解
if (viewInject == null)
continue; //获取注解里面的Id
int valueId = viewInject.value();
try {
//用反射调用findViewById()方法
Method findViewById = context.getClass().getMethod("findViewById",int.class);
View view = (View) findViewById.invoke(context,valueId);
//反射访问私有成员,必须加上这句
field.setAccessible(true);
//然后对这个属性复制
field.set(context,view);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
} private static void injectLayout(Object context) {
int layoutId = 0; //获得类
Class<?> clazz = context.getClass(); //获得该类声明的注解
ContentView contentView = clazz.getAnnotation(ContentView.class);
//如果该类没有声明注解
if (contentView == null)
{
return;
} //获得注解里面设置的Id
layoutId = contentView.value(); try {
//利用反射调用setContentView()方法
Method setContentView = context.getClass().getMethod("setContentView",int.class);
setContentView.invoke(context,layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} } }

具体含义请看注释。

三、定义一个BaseActivity

public class BaseActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectUtils.initContext(this);
}
}

四、实现我们的activity

//给该class加上我们自定义的注解,InjectUtils会通过找到
//注解里面的R.layout.activity_main,然后通过反射调用
//setContentView()方法
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity { //给该组件加上我们自定义的注解,InjectUtils会通过找到
//注解里面的R.id.xx,然后通过反射调用
//findViewById()方法找到控件
@ViewInject(R.id.text1)
private TextView textView1;
@ViewInject(R.id.text2)
private TextView textView2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); textView1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView1.setText("text1");
}
}); textView2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView2.setText("text2");
}
});
}
}

要注意一点:如果某个注解属性使用value作为名称如ContentView中的value,那么赋值的时候可以直接@ContentView(类的ID),但是如果你使用的是其他名称,比如下面这个注解:

public @interface Person
{
//name是属性而不是方法,t是它的默认值,在定义的时候可以不用给定默认值
String name() default t;
}

那么必须@Person(name=xx)这样调用

												

自定义xUtils框架的更多相关文章

  1. xUtils框架的使用

    xUtils简介 xUtils 包含了很多实用的android工具,xUtils 源于Afinal框架,对Afinal进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持,拥有 ...

  2. Android Xutils 框架(转)

    Android Xutils 框架 (转) 目录(?)[-] xUtils简介 目前xUtils主要有四大模块 使用xUtils快速开发框架需要有以下权限 混淆时注意事项 DbUtils使用方法 Vi ...

  3. XUtils框架的学习(一)

    一  xutils框架引入到AndroidStudio工程,最简单的方法:① 在APP的build.gradle里面加入 compile 'org.xutils:xutils:3.3.36'.② 一定 ...

  4. 自定义MVC框架

    我们在学习自定义MVC框架的时候常常会听到Model1 ,Model2和MVC.那么什么是Model1 什么是Model2什么又是MVC呢? 什么是Model1? Model1就是一种纯jsp开发技术 ...

  5. Struts2 自定义MVC框架

    一.Model1与Model2: Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起. Model2:Model2是在Model1的基础上,将业务逻辑的代码分离开来,单独形 ...

  6. JDBC 学习笔记(四)—— 自定义JDBC框架+Apache—DBUtils框架+事务管理+操作多表

    本文目录:       1.自定义JDBC框架 ——数据库元数据:DataBaseMetaData        2.自定义JDBC框架 ——数据库元数据:DataBaseMetaData       ...

  7. xUTils框架的学习(二)

    这章讲的是框架的DbUtils模块的学习 三 xUtils框架的DButils模块 最开始接触这个框架就是从数据库模块开始的.当时的需求是需要记录用户的登录数据,保存在本地以便进行离线登录.首先想到的 ...

  8. XUTils框架的学习(三)

    前面两章说了xutils框架的引入和注解模块的使用和数据库模块的使用,想了解的朋友可以去看看. 前面在说数据库模块的操作的时候是手动创建数据库并保存在asset文件夹里面,再通过I/O将数据库写进应用 ...

  9. 【Electron】Electron开发入门(八):自定义electron框架外壳(shell)的菜单(Menu)

    1.自定义electron框架外壳(shell)的菜单(Menu) electron的main.js里代码: const Menu = require('electron').Menu; var te ...

随机推荐

  1. 如何在微信小程序定义全局变量、全局函数、如何实现 函数复用 模块化开发等问题详解

    1.如何定义全局数据 在app.js的App({})中定义的数据或函数都是全局的,在页面中可以通过var app = getApp();  app.function/key的方式调用,不过我们没有必要 ...

  2. JVM性能调优监控命令jps、jinfo、jstat、jmap+jhat、jstack使用详解

    JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jinfo.jstat.jmap+jhat.jstack等小巧的工具,本博客希望能起抛砖 ...

  3. 美团App用户界面分析

    关于美团 美团网成立于2010年,合并前是中国销售额最大的独立团购 App.美团网2014年全年交易额突破460亿元,较去年增长180%以上,市场份额占比超60%,用户数超2亿~ 美团 App 用户界 ...

  4. Kubernetes 笔记 07 豌豆荚之旅(二)

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Hi,大家好, ...

  5. BBS论坛(十二)

    12.1.图形验证码生成 (1)utils/captcha/init.py import random import string # Image:一个画布 # ImageDraw:一个画笔 # Im ...

  6. Django知识点

    一.Django        pip3 install django            C:\Python35\Scripts        # 创建Django工程    django-adm ...

  7. 『没有上司的舞会 树形DP』

    树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...

  8. 在阿里云 ECS 搭建 nginx https nodejs 环境 (一、 nginx)

    首先介绍下相关环境.软件的版本 1.阿里云 ECS . ubuntu-14.04.5 LTS 2.nginx 版本 1.9.2 可能会遇到的问题: 一.在 ssh 服务器上的时候,提示 这个时候需要将 ...

  9. gradle插件从3.2.0升级到3.2.1后报错Error: Cannot create directory 项目目录\thirdlib\build\intermediates\packaged_res\debug\drawable

    报错信息如下:  解决方案: 删除thirdlib\build目录,然后重新编译. 但是紧接着又会报类似的错误,只不过build目录变成其他module的了. 所以,先clear build,然后再重 ...

  10. ArrayList循环遍历并删除元素的常见陷阱

    在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug.不妨把这个问题当做一道面试题目,我想一定能难道不少的人.今天就给大家说一下在ArrayList循环 ...