从无到有手写ButterKnife框架

导航

一、代码的演进
二、butterKnife反射调用
三、javapoet自动生成模板代码
四、apt与注解
五、注解支持多层继承
六、apt调试
七、javapoet语法

1、前言

javapoet解决重复模板代码编写问题
模板代码都类似,这样重复写来写去很烦
javapoet会是一阵强心剂

语法主要 @see https://github.com/square/javapoet
编写模板代码切记从上往下写,符合人的习惯,并且不会遗漏,

现写类,再写变量,再写方法,最后文件输出

javapoet模板代码编写

模板如下:

/**
 * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY CHENTONG.
 */
public class FirstActivity_ViewBinding implements Unbinder {
  private FirstActivity target;

  @UiThread
  public FirstActivity_ViewBinding(FirstActivity target, View source) {
    this.target = target;
    target.helloTv = source.findViewById( R.id.helloTv );
  }

  @Override
  public void unbind() {
    target.helloTv = null;
  }
}

1、模板要抽出变与不变的地方
不变的放在常量类中,变的用poet写
javapoet代码如下:
//引入两个类 或者可以采用Class.forName()

public interface Unbinder {
    void unbind();

    //空方法
    Unbinder EMPTY = new Unbinder() {
        @Override public void unbind() { }
    };
}

public class View {
}

//自动输出代码

public final class JavaPoet {

    private static final String SUFFIX = "_ViewBinding";

    private static final String JAVA_DOC = "DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY CHENTONG.\n";

    public static void main(String[] args) {

        try {
            gennerateCode(JavaPoet.class);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void gennerateCode(Class target) throws ClassNotFoundException, IOException {

        //类全路径
        String qualifiedName = target.getName().toString();
        //包名
        String packageName = qualifiedName.substring( 0, qualifiedName.lastIndexOf( "." ) );
        //类文件
        String fileName = target.getSimpleName() + SUFFIX;

        //eg:public class FirstActivity_ViewBinding implements Unbinder
        //构造类
        TypeSpec.Builder typeBuilder = TypeSpec.classBuilder( fileName )
                .addJavadoc( JAVA_DOC )
                .addModifiers( Modifier.PUBLIC )
                .addSuperinterface( Unbinder.class );

        //eg:private FirstActivity target;
        FieldSpec fieldSpec = FieldSpec.builder( target,"target",Modifier.PRIVATE ).build();

        //field添加当前类中
        typeBuilder.addField( fieldSpec );

        //eg:@UiThread
        //  public FirstActivity_ViewBinding(FirstActivity target, View source) {
        //    this.target = target;
        //    target.helloTv = source.findViewById( R.id.helloTv );
        //  }
        //构造方法
        MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder()
//                                    .addAnnotation( UiThread.class )
                                    .addModifiers( Modifier.PUBLIC )
                                    .addParameter( target,"target" )
                                    .addParameter( View.class,"source" );

        constructorBuilder.addStatement( "this.target = target" );
        constructorBuilder.addStatement( "target.helloTv = source.findViewById( R.id.helloTv )" );


        //构造方法添加到类中
        typeBuilder.addMethod( constructorBuilder.build() );

        //eg:@Override
        //  public void unbind() {
        //    target.helloTv = null;
        //  }
        //解绑方法
        MethodSpec.Builder unbindBuilder = MethodSpec.methodBuilder( "unbind" )
                .addAnnotation( Override.class )
                .addModifiers( Modifier.PUBLIC )
                .returns( void.class );

        unbindBuilder.addStatement( "target.helloTv = null" );

        //解绑方法添加类中
        typeBuilder.addMethod( unbindBuilder.build() );

        //创建文件 并且输出打印到到System.out
        JavaFile.builder( packageName, typeBuilder.build()).build().writeTo( System.out );
    }

}

以上代码,亲测可用

从无到有手写butterKnife框架

https://github.com/yinlingchaoliu/JavaPoetDemo

你可能感兴趣的:(从无到有手写ButterKnife框架)