Skip to content

Instantly share code, notes, and snippets.

@geniusmart
Created April 11, 2017 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geniusmart/ff787a347c0c86153d51c56eaef037f4 to your computer and use it in GitHub Desktop.
Save geniusmart/ff787a347c0c86153d51c56eaef037f4 to your computer and use it in GitHub Desktop.
ButterKnife 中 JavaPoet 的运用
package butterknife.compiler;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import org.junit.Test;
import java.io.IOException;
import javax.lang.model.element.Modifier;
import static butterknife.compiler.BindingSet.UTILS;
import static javax.lang.model.element.Modifier.PUBLIC;
/**
* Created by geniusmart on 2017/4/11.
*/
public class PoetAboutButterKnife {
private static final ClassName VIEW = ClassName.get("android.view", "View");
private static final ClassName UNBINDER = ClassName.get("butterknife", "Unbinder");
private static final ClassName UI_THREAD =
ClassName.get("android.support.annotation", "UiThread");
private static final ClassName CALL_SUPER =
ClassName.get("android.support.annotation", "CallSuper");
/**
* 执行后生成代码
*/
@Test
public void poet() throws IOException, ClassNotFoundException {
Class<?> activityClass = Class.forName("com.geniusmart.TestActivity");
// 创建属性
FieldSpec targetField = FieldSpec.builder(activityClass, "target")
.addModifiers(Modifier.PRIVATE)
.build();
//创建构造器1
MethodSpec constructorForActivity = MethodSpec.constructorBuilder()
.addAnnotation(UI_THREAD)
.addModifiers(PUBLIC)
.addParameter(activityClass, "target")
.addStatement("this(target, target.getWindow().getDecorView())")
.build();
// 生成程序片段:target.one = Utils.findRequiredView(source, 1, "field 'one'");
CodeBlock codeBlock = CodeBlock.builder()
.add("target.$L = ", "one")// 属性名 one 实际上应该通过注解获取
.add("$T.findRequiredView", UTILS)
.add("(source, $L", 1) //属性值实际上应该通过注解获取
.add(", $S", "field 'one'")
.add(")")
.build();
// 创建构造器2
MethodSpec otherConstructor = MethodSpec.constructorBuilder()
.addAnnotation(UI_THREAD)
.addModifiers(PUBLIC)
.addParameter(activityClass, "target")
.addParameter(VIEW, "source")
.addStatement("this.target = target")
.addStatement("$L", codeBlock) // 增加程序片段
.build();
// 创建解构函数 unbind
MethodSpec unBindeMethod = MethodSpec.methodBuilder("unbind")
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addAnnotation(CALL_SUPER)
.addStatement("$T target = this.target", activityClass)
.addStatement("if (target == null) throw new $T($S)", IllegalStateException.class,
"Bindings already cleared.")
.addStatement("$N = null", "this.target")
.addStatement("target.$L = null", "one")
.build();
// 创建类
TypeSpec typeSpec = TypeSpec.classBuilder("TestActivity_ViewBinding")
.addModifiers(PUBLIC) // 类为public
.addSuperinterface(UNBINDER) // 类为Unbinder的实现类
.addField(targetField) // 生成属性 private TestActivity target
.addMethod(constructorForActivity) // 生成构造器1
.addMethod(otherConstructor) // 生成构造器2
.addMethod(unBindeMethod) // 生成unbind()方法
.build();
// 生成 Java 文件
JavaFile javaFile = JavaFile.builder("com.geniusmart", typeSpec)//包名和类
.addFileComment("Generated code from Butter Knife. Do not modify!")
.build();
javaFile.writeTo(System.out);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment