日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android—APT实践

發(fā)布時(shí)間:2023/12/18 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android—APT实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

APT可以根據(jù)注解,在編譯時(shí)生成代碼。

1.?? ?創(chuàng)建兩個(gè)java library

?

2.?? ?依賴

factory-compiler的依賴

dependencies {implementation 'com.google.auto.service:auto-service:1.0-rc4'implementation project(':annotation')implementation 'com.squareup:javapoet:1.10.0'annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4' }

?app的

implementation project(':annotation') annotationProcessor project(':factory-compiler')

3.?? ?創(chuàng)建注解

@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface Factory {Class type();String id();}

4.?? ?注解使用

在app中創(chuàng)建接口,還有對(duì)應(yīng)實(shí)現(xiàn)類(lèi)

public interface IShape {void show(); }@Factory(type = IShape.class, id = "Circle") public class Circle implements IShape {@Overridepublic void show() {System.out.println("Circle");} }@Factory(type = IShape.class, id = "Rectangle") public class Rectangle implements IShape {@Overridepublic void show() {System.out.println("Rectangle");} }

在MainActivity中使用

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);IShapeFactory iShapeFactory = new IShapeFactory();IShape circle = iShapeFactory.create("Circle");TextView tv = findViewById(R.id.tv);tv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {circle.show();}});}@Overrideprotected void onResume() {super.onResume();} }

此時(shí)我們還沒(méi)有IShapeFactory這個(gè)類(lèi),需要用APT在編譯生成。

5.?? ?實(shí)現(xiàn)APT

首先我們創(chuàng)建兩個(gè)實(shí)體類(lèi)

public class FactoryAnnotatedClass {private TypeElement typeElement;private String canonicalName;private String simpleTypeName;private final String id;public FactoryAnnotatedClass(TypeElement classElement) {this.typeElement = classElement;Factory annotation = classElement.getAnnotation(Factory.class);id = annotation.id();try { // 該類(lèi)已經(jīng)被編譯Class<?> clazz = annotation.type();canonicalName = clazz.getCanonicalName();simpleTypeName = clazz.getSimpleName();} catch (MirroredTypeException mte) {// 該類(lèi)未被編譯DeclaredType classTypeMirror = (DeclaredType) mte.getTypeMirror();TypeElement classTypeElement = (TypeElement) classTypeMirror.asElement();canonicalName = classTypeElement.getQualifiedName().toString();simpleTypeName = classTypeElement.getSimpleName().toString();}}……get方法 } public class FactoryGroup {private static final String SUFFIX = "Factory";public final String qualifiedClassName;private final Map<String, FactoryAnnotatedClass> itemsMap = new LinkedHashMap<>();public FactoryGroup(String qualifiedClassName) {this.qualifiedClassName = qualifiedClassName;}public void add(FactoryAnnotatedClass toInsert) {itemsMap.put(toInsert.getId(), toInsert);}public void generateCode(Elements elementUtils, Filer filer) {TypeElement superClassName = elementUtils.getTypeElement(qualifiedClassName);String factoryClassName = superClassName.getSimpleName() + SUFFIX;PackageElement pkg = elementUtils.getPackageOf(superClassName);String packageName = pkg.isUnnamed() ? null : pkg.getQualifiedName().toString();MethodSpec.Builder method = MethodSpec.methodBuilder("create").addModifiers(Modifier.PUBLIC).addParameter(String.class, "id").returns(TypeName.get(superClassName.asType()));method.beginControlFlow("if (id == null)").addStatement("throw new IllegalArgumentException($S)", "id is null!").endControlFlow();for (FactoryAnnotatedClass item : itemsMap.values()) {method.beginControlFlow("if ($S.equals(id))", item.getId()).addStatement("return new $L()", item.getTypeElement().getQualifiedName().toString()).endControlFlow();System.out.println("QualifiedName "+item.getTypeElement().getQualifiedName().toString());}method.addStatement("throw new IllegalArgumentException($S + id)", "Unknown id = ");TypeSpec typeSpec = TypeSpec.classBuilder(factoryClassName).addModifiers(Modifier.PUBLIC).addMethod(method.build()).build();try {if (packageName != null) {JavaFile.builder(packageName, typeSpec).build().writeTo(filer);}} catch (IOException e) {e.printStackTrace();}} }

最主要的就是generateCode方法,里面利用了JavaPoet生成代碼。

接下來(lái)創(chuàng)建一個(gè)類(lèi)繼承AbstractProcessor,主要實(shí)現(xiàn)下面兩個(gè)方法。

@AutoService(Processor.class) public class FactoryProcessor extends AbstractProcessor{private final Map<String, FactoryGroup> factoryClasses = new LinkedHashMap<>();@Overridepublic Set<String> getSupportedAnnotationTypes() {Set<String> annotations = new LinkedHashSet<>();annotations.add(Factory.class.getCanonicalName());return annotations;}@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {for (TypeElement element:set){// 通過(guò)RoundEnvironment獲取到所有被@Factory注解的對(duì)象Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(element);for (Element annotatedElement : elements) {TypeElement typeElement = (TypeElement) annotatedElement;FactoryAnnotatedClass annotatedClass = new FactoryAnnotatedClass(typeElement);FactoryGroup factoryGroup = factoryClasses.get(annotatedClass.getCanonicalName());if (factoryGroup == null) {String qualifiedGroupName = annotatedClass.getCanonicalName();factoryGroup = new FactoryGroup(qualifiedGroupName);factoryClasses.put(qualifiedGroupName, factoryGroup);}factoryGroup.add(annotatedClass);}for (FactoryGroup factoryGroup : factoryClasses.values()) {factoryGroup.generateCode(processingEnv.getElementUtils(), processingEnv.getFiler());}return true;}return false;} }

process方法會(huì)被多次調(diào)用,方法參數(shù)中的set是我們注解類(lèi)所對(duì)應(yīng)的TypeElement對(duì)象,僅當(dāng)set不為空時(shí),我們才去操作。

?然后調(diào)用RoundEnvironment的getElementsAnnotatedWith方法獲取到使用了改注解的類(lèi)的TypeElement對(duì)象(既Circle、Rectangle)。

然后我們把這兩個(gè)TypeElement對(duì)象封裝成FactoryAnnotatedClass對(duì)象,存放到factoryGroup中,簡(jiǎn)單說(shuō)factoryGroup就是用來(lái)存放使用了同一個(gè)注解類(lèi)的對(duì)象,為了方便我們創(chuàng)建多個(gè)注解一起使用所以又創(chuàng)建了一個(gè)map對(duì)象(既f(wàn)actoryClasses)來(lái)存放factoryGroup,然后我們調(diào)用generateCode方法生成對(duì)應(yīng)java文件。

?在generateCode方法中,我們通過(guò)獲取Circle、Rectangle類(lèi)注解的id,來(lái)生成代碼,rebuild之后即可看到對(duì)應(yīng)文件。

?

優(yōu)點(diǎn):

1、當(dāng)我們需要再創(chuàng)建一個(gè)實(shí)現(xiàn)類(lèi)時(shí),只需要給實(shí)現(xiàn)類(lèi)標(biāo)上注解就可以,不想要去添加工廠類(lèi)的代碼。如果是自己編寫(xiě)的工廠類(lèi)則需要再加一段代碼。

2、APT>反射,解析注解可以不需要用反射的方式,APT在調(diào)式期間就可以解析。

JavaPoet使用文檔: https://github.com/aheckl/javapoet

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Android—APT实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。