-
-
Save geniusmart/ff787a347c0c86153d51c56eaef037f4 to your computer and use it in GitHub Desktop.
ButterKnife 中 JavaPoet 的运用
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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