自定义xutils框架

妖久 妖久     2022-10-09     429

关键词:

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)这样调用

android开发技巧之使用自定义注解

前言 一些优秀的开源框架如比较早的xUtils网络加载框架及现在最新版本的greenDao3.XORM框架支持注解,注解的使用可以使得我们的代码架构变得更加清晰,同时也更能体现出面向对象语言的继承的魅力。我们在Android开发... 查看详情

xutils3框架使用

目前Android开发很火的一个框架Xutils框架。它有四个模块:1、ViewUtils。2、HttpUtils。3、DbUtils。4、BitmapUtils。记得是去年的差不多这个时候,我的大学老师张老师介绍我去学习Xutils框架,当时项目有很多对数据库的操作,所以刚学... 查看详情

xutils3框架的基本使用方法(代码片段)

...例都是基于XUtils3的API语法进行的演示。相信大家对这个框架也都了解过,下面简单介绍下XUtils3的一些基本知识。XUtils3一共有4大功能:注解模块,网络模块,图片加载模块,数据库模块。使用XUtils只需要在libs... 查看详情

xutils3框架的基本用法

...例都是基于XUtils3的API语法进行的演示。相信大家对这个框架也都了解过,以下简介下XUtils3的一些基本知识。XUtils3一共同拥有4大功能:注解模块,网络模块。图片载入模块。数据库模块。使用X 查看详情

进展xutils3框架的使用

刚刚SLP迎来了一个飞跃——成功地使用XUtils3框架从LL资源网站上拉取LIVE相关信息并显示成列表。效果如下:  查看详情

xutils3的简单介绍

...Utils是基于Afinal开发的目前功能比较完善的一个Android开源框架,最近又发布了xUtil3.0,在增加新功能的同时又提高了框架的性能。1.xUtils包含了很多实用的android工具;xUtils支持超大文件(超过2G)上传,更全面的http请求协议支持(11... 查看详情

xutils,okhttp,volley,retrofit对比

Xutils这个框架非常全面,可以进行网络请求,可以进行图片加载处理,可以数据储存,还可以对view进行注解,使用这个框架非常方便,但是缺点也是非常明显的,使用这个项目,会导致项目对这个框架依赖非常的严重,一旦这... 查看详情

xutils开源框架的使用(httputils支持多线程断点续传)

 XUtils项目下载地址:https://github.com/wyouflf/xUtilsXUtils中包含的四大模块:       1、DbUtils模块       2、ViewUtils模块       3、HttpUtils模块:支持同步,异步方式的请求;支持大文件上传,上传大文件... 查看详情

使用自定义框架

】使用自定义框架【英文标题】:Usingacustomframework【发布时间】:2010-09-0920:32:45【问题描述】:我得到的错误:in/Users/robert/Documents/funWithFrameworks/build/Debug-iphonesimulator/funWithFrameworks.framework/funWithFrameworks,can\'tlinkwithamainexecutab 查看详情

实体框架:创建自定义属性

】实体框架:创建自定义属性【英文标题】:EntityFramework:Creatingcustomproperties【发布时间】:2010-10-0115:30:35【问题描述】:考虑在DAL程序集中实现实体框架。我需要向实体添加自定义只读属性。PersonClass,如DB中所定义,包含以下... 查看详情

带有实体框架的自定义函数

】带有实体框架的自定义函数【英文标题】:CustomFunctionswithEntityFramework【发布时间】:2014-08-1210:13:59【问题描述】:如何在实体框架中使用自定义函数?我正在尝试使用实体框架调用模型定义的函数。我使用.NetFramework4.5我正在... 查看详情

使用自定义框架从目录运行 PHPUnit 测试

】使用自定义框架从目录运行PHPUnit测试【英文标题】:RunningPHPUnittestsfromdirectorywithcustomframework【发布时间】:2012-05-2106:20:56【问题描述】:对于我们的项目,我在PHPUnit框架之上创建了一个框架,它可以帮助我们完成编写单元测... 查看详情

将螺栓框架添加到自定义 Swift 框架错误

】将螺栓框架添加到自定义Swift框架错误【英文标题】:AddingBoltsFrameworktoCustomSwiftFrameworkError【发布时间】:2015-12-2522:30:52【问题描述】:我正在尝试创建一个自定义Swift框架。在该框架中,我添加了Bolts框架。在其他项目中尝试... 查看详情

新闻client案例开发

...ViewPager),android网络通信(http通信)。开源组件(xutils框架-HttpUtils模块、xutils框架-BitmapUtils模块),开源框架(library)。所需jar包:xUtils、gson、android-supp 查看详情

线程1:自定义框架Swift中Reachability框架中的signal SIGABRT

】线程1:自定义框架Swift中Reachability框架中的signalSIGABRT【英文标题】:Thread1:signalSIGABRTinReachabilityframeworkincustomframeworkSwift【发布时间】:2018-09-0614:35:08【问题描述】:我开发了一个自定义框架,并使用了通过“Carthage”导入的“... 查看详情

htmltumblr自定义主题框架(代码片段)

查看详情

自定义jdbc框架

 获取元数据元数据-DataBaseMetaData     DatabaseMetaDatameta=con.getMetaData();getDatabaseProductName()、getDatabaseMajorVersion()、getDatabaseProductVersion()、getDriverName()、getURL()、getUserName()&nb 查看详情

您如何确定自定义 UINavigationItem.titleView 的大小/框架?

】您如何确定自定义UINavigationItem.titleView的大小/框架?【英文标题】:Howdoyoudeterminethesize/frameofacustomUINavigationItem.titleView?【发布时间】:2011-11-2718:24:51【问题描述】:在创建自定义视图并将其分配给navigationItem.titleView属性后,它... 查看详情