zoukankan      html  css  js  c++  java
  • 自定义xUtils框架

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

    
    
  • 相关阅读:
    NGINX原理分析 之 SLAB分配机制
    graphviz
    使用git Rebase让历史变得清晰
    An Implementation of Double-Array Trie
    转录组差异表达分析小实战(一)
    简单使用limma做差异分析
    简单使用DESeq2/EdgeR做差异分析
    简单使用DESeq做差异分析
    HISAT,sTRINGTIE,ballgown三款RNA-seq信息分析软件
    转录组的组装Stingtie和Cufflinks
  • 原文地址:https://www.cnblogs.com/tangZH/p/8284180.html
Copyright © 2011-2022 走看看