赞
踩
本人从事开发工作也有多年,目前坐标湖南长沙,以前在各种平台也发过一些文章但是都没有坚持下来;
我初步规划是写一个完整的项目系列文章期望能坚持下来。
为什么会想到要写呢?
其一、眨眼就到了而立之年,觉得自己记忆力也是下降久做过的东西总是记不起,果然是好记性不如烂笔头。
其二、这么多年白嫖了网上很多的文章,视频,一直觉得应该分享一些东西但总是沉不下心去做。
其三、可能写的不好至少也留下一些东西,也是希望能帮助到一些朋友。
最近在研究鸿蒙系统写了一些简单的东西,鸿蒙的有些UI操作,比如findComponentById,setClickedListener 这些比较繁琐于是就尝试用APT做一个尝试实现一个简单的butterknife。
如不知道请参考Hello world: 鸿蒙初尝试.
我这里选择了Empty Feature Ability(JAVA)
添加BindView和OnClick注解
鸿蒙编译器做到修改布局后及时编译。这个时候我们可以做如下操作!
1.要么运行一次。
2.用命令行运行一次Gradle编译命令
3.当然我们不用这么麻烦直接图形化点一下Gradle执行
添加几个断点预备Debug看看
模块引用
添加调用
运行结果 证明
点击第二个控件后
证明这样写在鸿蒙系统中也是没有问题的。接下来我们只需要试试用APT生成MainAbilitySlice$ViewBinding类后可不可以调用到就可以了。
添加ButterKnifeProcessor
添加需要的包引用
在 entry中添加对于生成的库引用
修改ButterKnifeProcessor文件
package com.lyl.butterknife.compiler; import com.google.auto.service.AutoService; import com.lyl.butterknife.annotations.BindView; import com.lyl.butterknife.annotations.OnClick; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.*; @AutoService(Processor.class) public final class ButterKnifeProcessor extends AbstractProcessor { private Filer mFiler; private Elements mElementUtils; private Messager mMessager; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); mElementUtils = processingEnv.getElementUtils(); mMessager = processingEnv.getMessager(); mFiler = processingEnv.getFiler(); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } private Set<Class<? extends Annotation>> getSupportedAnnotations() { Set<Class<? extends Annotation>> annotations = new LinkedHashSet<>(); annotations.add(BindView.class); annotations.add(OnClick.class); return annotations; } @Override public Set<String> getSupportedAnnotationTypes() { Set<String> types = new LinkedHashSet<>(); for (Class<? extends Annotation> annotation : getSupportedAnnotations()) { types.add(annotation.getCanonicalName()); } return types; } @Override public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment env) { Map<Element, List<BuildObject>> elementListMap = findAndParseTargets(env); for (Map.Entry<Element, List<BuildObject>> entry : elementListMap.entrySet()) { Element enclosingElement = entry.getKey(); List<BuildObject> viewBindElements = entry.getValue(); String activityClassNameStr = enclosingElement.getSimpleName().toString(); ClassName activityClassName = ClassName.bestGuess(activityClassNameStr); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(activityClassNameStr + "$ViewBinding") .addModifiers(Modifier.FINAL, Modifier.PUBLIC); buildElementConstructorMethod(activityClassName, classBuilder, viewBindElements); try { String packageName = mElementUtils.getPackageOf(enclosingElement).getQualifiedName().toString(); JavaFile.builder(packageName, classBuilder.build()) .build().writeTo(mFiler); } catch (IOException e) { e.printStackTrace(); System.out.println(e.getMessage()); } } return true; } private void buildElementConstructorMethod(ClassName activityClassName, TypeSpec.Builder classBuilder, List<BuildObject> buildObject) { MethodSpec.Builder constructorMethodBuilder = MethodSpec.constructorBuilder() .addParameter(activityClassName, "target",Modifier.FINAL).addModifiers(Modifier.PUBLIC); for (BuildObject object : buildObject) { assembleConstructorMethod(constructorMethodBuilder, object); } classBuilder.addMethod(constructorMethodBuilder.build()); } private void assembleConstructorMethod(MethodSpec.Builder constructorMethodBuilder, BuildObject buildObject) { System.out.println(buildObject.clazz == BindView.class); if (buildObject.clazz == BindView.class) { String filedName = buildObject.element.getSimpleName().toString(); String type = buildObject.element.asType().toString(); System.out.println(filedName); System.out.println(type); int resId = buildObject.element.getAnnotation(BindView.class).value(); constructorMethodBuilder.addStatement("target.$L =($L) target.findComponentById($L)", filedName, type, resId); } else if (buildObject.clazz == OnClick.class) { String filedName = buildObject.element.getSimpleName().toString(); String type = buildObject.element.asType().toString(); System.out.println(filedName); System.out.println(type); int[] resIds = buildObject.element.getAnnotation(OnClick.class).value(); System.out.println(resIds); for (int resId : resIds) { constructorMethodBuilder.addStatement(" target.findComponentById($L).setClickedListener(new ohos.agp.components.Component.ClickedListener() {@Override public void onClick(ohos.agp.components.Component component) {target.$N(component);}})", resId, filedName); } } } private Map<Element, List<BuildObject>> findAndParseTargets(RoundEnvironment env) { Map<Element, List<BuildObject>> elementListMap = new LinkedHashMap<>(); for (Class<? extends Annotation> clazz : getSupportedAnnotations()) { for (Element element : env.getElementsAnnotatedWith(clazz)) { try { Element enclosingElement = element.getEnclosingElement(); List<BuildObject> elements = elementListMap.get(enclosingElement); BuildObject buildObject = new BuildObject(element, clazz); if (elements == null) { elements = new ArrayList<>(); } System.out.println(enclosingElement.getSimpleName()); System.out.println(element.getSimpleName()); elements.add(buildObject); elementListMap.put(enclosingElement, elements); } catch (Exception e) { } } } return elementListMap; } }
其中用到的一个BuildObject
package com.lyl.butterknife.compiler; import javax.lang.model.element.Element; public class BuildObject { Element element; Class clazz; public BuildObject(Element element, Class clazz) { this.element = element; this.clazz = clazz; } public Element getElement() { return element; } public void setElement(Element element) { this.element = element; } public Class getClazz() { return clazz; } public void setClazz(Class clazz) { this.clazz = clazz; } }
执行前把之前自己手写的类改个名
执行命令
这里没有运行结果图…因为崩溃了…
错误是
虽然标记中点位置都生成了但javac里面并没有。
尝试失败!
当然我们可以采取一些其他方式让他打包进去…
但我们现在确实是失败了
具体为什么鸿蒙的IDE为什么没有把他编译进去的原因暂时没有去深究。
如果朋友找到原因或者我有哪个地方弄错了可以联系我!
生成代码的如果一些不懂得可以结合下面这篇文章查看
链接: 搭建Android客户端APP架构——《编译时APT技术》
链接: Javapoet说明
链接: 这个项目的源码地址
//TODO 给我感觉写代码远比写文章要轻松....致敬所有写文分享的人
我是先好Demo,再写文章的,写文章的时间远要比写Demo的时间久。
这篇文章主要写了一些简单的鸿蒙 APT的尝试,如有不懂之处或者写得不甚明了的地方可以留言。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。