手写ButterKnife---配置和了解javapoet

javapoet:大师参考链接:https://blog.csdn.net/IO_Field/article/details/89355941
总共3个module,之间的联系
在这里插入图片描述

创建java library:Lib_annontation

创建注解类:
@Target(ElementType.FIELD) //声明注解作用域(FIELD:成员变量,METHOD:方法...)
@Retention(RetentionPolicy.SOURCE) //注解处理的生命周期SOURCE:只在java文件有用,即编译class文件前,Class/RUNTIME
public @interface BindView {
    int value();
}

创建java library:Lib_complier

配置Lib_complier的build.gradle:
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.google.auto.service:auto-service:1.0-rc4'
    implementation 'com.squareup:javapoet:1.11.1' 
    compile project(path: ':lib_annonation')//依赖注解类
}
 Javepoet(poet:java诗人):动态生成代码,与反射相似。将类、方法、变量都为对象

1.创建注解处理器,一个基础



@AutoService(Processor.class)
public class MyProcess extends AbstractProcessor {
    /**声明注解处理器的注解
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new HashSet<>();
        types.add(BindView.class.getCanonicalName());
        return types;
    }
    /**声明注解处理器的源版本
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return processingEnv.getSourceVersion();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(BindView.class);

        // 接口:给注解处理器创建的类使用
        ClassName interface_viewbinder = ClassName.get("com.zzn.test5555555", "ViewBind");

        //key为Activity名,Value为成员遍历的集合
        Map<String, List<VariableElement>> map = new HashMap<>();

        getMap(map, elements);

        Iterator<String> activitylist = map.keySet().iterator();

        while (activitylist.hasNext()) {
            //类名 BBBBActivity
            String activityName = activitylist.next();
            //成员变量List
            List<VariableElement> fieldlist = map.get(activityName);
            //拿到第一个成员变量的上一级Element  这一级: element.toString() = com.zzn.test5555555.MainActivity
            Element enclosingElement = fieldlist.get(0).getEnclosingElement();
            TypeElement classElement = (TypeElement) enclosingElement;//获取节点的具体类型:MainActivity,可以拿父类和接口

            //方法参数设置:bind(MainActivity tager)
            TypeMirror typeMirror = enclosingElement.asType();
            TypeName typeName = TypeName.get(typeMirror);
            ParameterSpec parameterSpec = ParameterSpec.builder(typeName, "tager").build();

            //类的接口参数设置:implements ViewBind<MainActivity>    :ViewBind接口不是类中的需要 ClassName.getClassName方式获取
            //ParameterizedTypeName.get(ClassName,TypeName);  接口 / 泛型
            ParameterizedTypeName interface_Parame = ParameterizedTypeName.get(interface_viewbinder, typeName);


            //包名 获取2中方法
            String packageName = processingEnv.getElementUtils().getPackageOf(enclosingElement).toString();
            //String packageName = classElement.getEnclosingElement().toString();

            //创建方法
            MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("bind")
                    .addModifiers(Modifier.PUBLIC)
                    .addParameter(parameterSpec)
                    .returns(void.class);
            // 如:tager.button=(Button)tager.findViewById(2131165320);
            for (VariableElement variableElement : fieldlist) {
                //成员变量名字
                //成员变量类型
                //控件id
                String name = variableElement.getSimpleName().toString();
                TypeMirror typeMirror2 = variableElement.asType();
                //  FieldSpec fieldSpec=FieldSpec.builder(typeMirror,activityName).build();
                int id = variableElement.getAnnotation(BindView.class).value();
                methodBuilder.addStatement("tager.$N=($T)tager.findViewById($L)", name, typeMirror2, id);
            }
            //创建类 ==>public class MainActivity$ViewBinder implements ViewBind<MainActivity> {
            TypeSpec typeSpec = TypeSpec.classBuilder(activityName + "$ViewBinder")
                    .addModifiers(Modifier.PUBLIC)
                    .addSuperinterface(interface_Parame)//添加接口,接口泛型==》 ViewBind<MainActivity>
                    .addMethod(methodBuilder.build())
                    .build();
            //创建文件
            JavaFile javaFile = JavaFile.builder(packageName, typeSpec)
                    .addFileComment("注解处理器生成的类\n")
                    //通过注释打印几个Element
                    .addFileComment(enclosingElement.getEnclosingElement().toString() + "\n")
                    .addFileComment(enclosingElement.toString() + "\n")
                    .addFileComment(enclosingElement.getEnclosedElements().toString() + "\n")
                    .addFileComment(classElement.getSuperclass() + "\n")  //拿到继承的父类
                    .addFileComment(classElement.getInterfaces() + "\n")  //拿到接口
                    .addFileComment(classElement.getSimpleName() + "\n")  //拿到类名MainActivity
                    .addFileComment(classElement.getEnclosingElement().toString() + "\n")  //拿到类名MainActivity
                    // .addStaticImport(className)          //添加 import .....
                    .build();
            try {
                javaFile.writeTo(processingEnv.getFiler());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    //获取map key/value==》activity/成员变量list
    private void getMap(Map<String, List<VariableElement>> map, Set<? extends Element> elements) {
        for (Element element : elements) {
            VariableElement variableElement = (VariableElement) element;
            //getEnclosingElement 获取上一个节点 ,用于获取类名
            String activityName = variableElement.getEnclosingElement().getSimpleName().toString();
            List<VariableElement> list_field = map.get(activityName);
            if (list_field == null) {
                list_field = new ArrayList<>();
                map.put(activityName, list_field);
            }
            list_field.add(variableElement);//field -> list -> map
        }
    }
}

2.在处理的module的main目录下创建:javax.annotation.processing.Processor文件,填入处理器路径
创建原因好像是Gradle版本问题,没有该文件执行执行后没有生产java文件
在这里插入图片描述
文件内容:
在这里插入图片描述

使用注解处理器:

创建ButterKnife类,ViewBind接口:注解处理器创建的java类是实现该接口,然后利用重载,传递给不同Activity的处理器类,控件的初始化才能生效

配置build.gradle:
注意!annotationProcessor表示注解处理器依赖,如果用implementation就会报错
一个module一个注解处理器,如:lib_complier2是另外一个处理器,同样annotationProcessor

注意!如果想将注解和注解处理器写在同一个module,然后只依赖一个module那是不行的!理由太复杂
在这里插入图片描述
Activity中使用

 @BindView(R.id.texxt)
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BufferKnife2.bind(this);
        textView.setText("Hello JavaPoet!");

VindBind接口:泛型T为Activity

public interface ViewBind<T> {
void bind(T target);
}

ButterKnife

public class BufferKnife2 {
public static  void bind(Activity activity){
    String name=activity.getClass().getName()+"$ViewBinder";
    //MainActivity$ViewBinder 拿到自动注解生成的类名,
    try {
        ViewBind viewBind= (ViewBind) Class.forName(name).newInstance();
        viewBind.bind(activity);
    } catch (Exception e) {e.printStackTrace();}}}

Rebuild一下应该就能生成java路径:build/generated/source/apt/debug/包名/MainActivity$ViewBinder

package com.zzn.test5555555;

import android.widget.TextView;

public class MainActivity$ViewBinder implements ViewBind<MainActivity> {
  public void bind(MainActivity tager) {
    tager.textView=(TextView)tager.findViewById(2131165319);
  }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值