学习笔记-ButterKnife

为什么使用?

       1. 方便处理adapter里的viewHolder的绑定问题

       2. 简化代码,节省开发时间(代替android中对view的相关操作,减少大量的findViewById和setClickListener)

       3. 不影响运行性能和效率

       4. 代码清晰,可读性强

原理:

       利用注解和注解处理器针对每个类生成相对应的类,通过butterknife.bind(this)绑定这个类,通过反射机制操作类里的方法和变量

       注解:相当于一个标记

       注解处理器:相当于大脑

前期准备

     使用butterknife:

     implementation 'com.jackewharton:butterknife:9.0.0'   申明注解库

     annotationProcessor 'com.jackwharton:butterknife-compiler:9.0.0'   申明注解处理器

     自己写注解器:

     annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'  注解处理器申明(编译时运行)

     implementation  'com.google.auto.service:1.0-rc4'

      申明java版本

      compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

     添加插件:

    dependencies {
        classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0'
     }

简单说明

      绑定:Butterknife.bind(this)

      右键可以一键生成(需要添加插件:android butterknife zelezry),使用的时候鼠标需要停留在layoutView上(Generate - Generate Butterknife injections)

      可以绑定所有的source资源:@BindString(R.string.name) String appName;

      

使用

重点需要注册这个类是一个注解处理器:@AutoService(Processor.class)

继承AbstractProcessor类实现相关方法进行相应处理操作

1. 初始化工作(生成一个java文件)

    //生成文件对象

    Filter filter;

    * 实现init方法,参数是processingEnvironment(初始化数据)

        filter = processingEnvironment.getFilter();

    * 实现getSupportedAnnotationTypes(说明注解处理器要处理哪些注解)

        Set<String> types = new HashSet<>();

        types.add(BindView.class.getCanonicalName());//BindView是自己定义的注解名称

        最后return这个types

    * 实现getSupportedSourceVersion(申明当前注解支持的java版本)

        // 直接return一个sourceVersion对象

        return  processingEnv.getSourceVersion() -- processingEnv是父类成员变量

   * 实现process(写文件 - 包含俩个参数set结合和RoundEnviroment)

        说明:可以读取三种类型节点

                  1. 类节点 - TypeElement

                  2. 方法节点 - ExecutableElement

                  3. 变量节点 - VariableElement

        //获取模块中用到BindView的成员变量节点集合(指App中所有activity控件)

        Set<? extends Element> elementsAnnotateWith = roundEnvironment.getElementAnnotatesWith(接口类.class);

        //遍历文件进行Activity分离

        Map<String,List<VeriableElement>> map = new HashMap();

        /***额外的说明,注解处理器可以做很多事情,因为可以拿到类对象******
               Class class = variableElement.getEnclosingElement().getClass();
               Filed[] = class.getDeclaredFields();//拿到类里所有变量
               Method[] class.getDeclaredMethods();//拿到类里所有方法
         *****************************************************************/

        for(Element element: elementsAnnotatedWith){

               VariableElement variableElement = (VariableElement)element;

                //获取类节点

                String activityName = variableElement.getEnclosingElement().getSimpleName().toString();

                List<VariableElement> variableElementList = map.get(activityName);

                if(variableElementList == null){

                        variableElementList = new ArrayList();

                        map.put(activityName,variableElementList);

                }

                variableElementList.add(variableElement);

        }

        //开始写文件

        if(map.size() > 0){

                Write write = null;

                Iterator<String> iterator = map.ketSet().iterator();

                while(iterator.hasNext()){

                        String activityName = iterator.next();

                        //获取到activity所对应的集合

                        List<VariableElement> variableElementList = map.get(activityName);

                        //获取父节点  -  类节点

                        TypeElement  enclosingElement= (TypeElement)variableEElementList.getEnclosingElement();

                       //通过成员变量到的包名
                       String packageName = processingEnv.getElementUtils().getPackageOf(enclosingElement).toString();
                       JavaFileObject sourceFile = filer.createSourceFile(packageName+"."+activityName+"_ViewBinding");
                       writer = sourceFile.openWriter();
                       writer.write("package "+packageName+";\n");//写类的第一句,包名
                       writer.write("import "+packageName+".IBinder;\n");//import引入包名
                       writer.write("public class "+activityName+"_ViewBinding implements

                                      IBinder<"+packageName+"."+activityName+">{\n");
                        writer.write("@OverRide\n  public void bind("+packageName+"."+activityName+" target){");
                        //遍历所有的控件
                       for(VariableElement variableElement:variableElements){
                               //获取到控件名字
                              String variableName = variableElement.getSimpleName().toString();
                               //获取控件id
                               int id = variableElement.getAnnotation(BindView.class).value();
                               //获取控件类型
                               TypeMirror typeMirror = variableElement.asType();
                              writer.write("target."+variableName+"=("+typeMirror+")target.findViewById("+id+");\n);
                       }
                    writer.write("{\n}\n");

                }

        }

        最后在finally中
           if(writer != null){
                try(){
                    writer.close();
                }catch(IOException e){

                }
            }

后续使用:

       

        创建一个类(该类要实现接口类)
            实现bind(){

            }
        类(java类执行注解类)
            public static void bind(Activity activity){
            activity.getClass().getName()+"_ViewBinding";
            Class<T> aClass = Class.forName(name);
            IBind iBinder = aClass.newInstance();
            iBinder.bind(activity);
            }
        接口类<T>(把当前activity传进去)
            void bind(T target);//可能是activity、fragment、service等

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值