自定义注解并生成类文件(kotlin实现)

1.新建一个Java Library 的module(文中示例为extent)

自定义注解并生成类文件(kotlin实现)_第1张图片

2.修改module gradle文件

apply plugin: 'java-library'
apply plugin: 'kotlin'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation rootProject.ext.dependencies['kotlin-stdlib-jdk7']
}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

其中,因为是基于kotlin实现,别忘了“apply plugin 'kotlin',还有就是需要设置编码兼容性,这里设置为1.8。

2.新建annotation和自定义AbstractProcessor文件

自定义注解并生成类文件(kotlin实现)_第2张图片(module结构)

其中ActivityAnnotation文件如下

package com.dingo.extent

@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityAnnotation(val layoutResId: String)

ExtentActivityProcessor文件如下,这里我只是简单的实现,其实可以根据需求有很大的发挥空间。

其中推荐'com.squareup:javapoet:1.9.0',这个第三方库可以帮助更加容易的生成一些复杂的类。

package com.dingo.extent

import java.io.IOException
import java.util.*
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.lang.model.util.Elements
import javax.tools.Diagnostic

class ExtentActivityProcessor : AbstractProcessor(){

    val templateClass = "/**\n" +
            " * Copyright (C) 2019~2099. All rights reserved.\n" +
            " */\n" +
            "package %s;\n" +
            "\n" +
            "import android.os.Bundle;\n" +
            "import android.support.annotation.Nullable;\n" +
            "import android.support.v7.app.AppCompatActivity;\n" +
            "\n" +
            "import com.dingo.newexproration.R;\n" +
            "\n" +
            "/**\n" +
            " * desc:\n" +
            " *\n" +
            " * @author dingo\n" +
            " * create at 2019/1/12 21:50\n" +
            " */\n" +
            "public class %s extends AppCompatActivity {\n" +
            "    @Override\n" +
            "    protected void onCreate(@Nullable Bundle savedInstanceState) {\n" +
            "        super.onCreate(savedInstanceState);\n" +
            "        setContentView(R.layout.%s);\n" +
            "    }\n" +
            "}"

    var mFiler: Filer? = null
    var mMessager: Messager? = null
    var mElementUtils: Elements? = null

    override fun init(processingEnvironment: ProcessingEnvironment?) {
        super.init(processingEnvironment)
        mFiler = processingEnvironment?.filer
        mMessager = processingEnvironment?.messager
        mElementUtils = processingEnvironment?.elementUtils
    }

    override fun process(annotations: MutableSet?, roundEnvironment: RoundEnvironment?): Boolean {

        annotations?.let{

            annotations.forEach { typeElement ->
                roundEnvironment?.getElementsAnnotatedWith(typeElement)?.forEach {

                    val packageName = mElementUtils?.getPackageOf(it)?.qualifiedName.toString()
                    mMessager?.printMessage(Diagnostic.Kind.NOTE, "packageName. : $packageName")
                    val className = it.simpleName.toString()
                    mMessager?.printMessage(Diagnostic.Kind.NOTE, "className. : $className")

                    val extentAnnotation = it.getAnnotation(ActivityAnnotation::class.java)
                    val layoutResId = extentAnnotation.layoutResId
                    mMessager?.printMessage(Diagnostic.Kind.NOTE, "layoutResId. : $layoutResId")

                    val fileContent = String.format(templateClass, packageName, className, layoutResId)
                    mMessager?.printMessage(Diagnostic.Kind.NOTE, "fileContent. : $fileContent")

                    createFile("$packageName.$className", fileContent)
                }
            }

        }

        return false
    }

    private fun createFile(fileName: String = "defaultClass", fileContent: String) {
        try {
            mFiler?.let {
                val writer = it.createSourceFile(fileName).openWriter()
                writer.write(fileContent)
                writer.flush()
                writer.close()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

    }

    override fun getSupportedSourceVersion(): SourceVersion {
        return SourceVersion.RELEASE_8
    }

    override fun getSupportedAnnotationTypes(): MutableSet {
        val types = LinkedHashSet()
        types.add(ActivityAnnotation::class.java.canonicalName)
        return types
    }
}

其中javax.annotation.processing.Processor中为ExtentActivityProcessor的声明

com.dingo.extent.ExtentActivityProcessor

4.引用module修改build.gradle文件(这里是app module引用)

在dependencies 中增加如下引用

implementation project(':extent')
annotationProcessor project(':extent')

5.使用

public class ActivityFactory {

    @ActivityAnnotation(layoutResId = "activity_main")
    Activity TestOneActivity;

    @ActivityAnnotation(layoutResId = "activity_game")
    Activity TestTwoActivity;
}

这里有个坑,在使用的时候需要使用Java类,不能使用Kotlin来使用自定义注解。否则不会自动生成相应的代码。

应该是kotlin还不够完善吧,相信以后可以在kotlin文件中使用。

6.查看生成的文件

自定义注解并生成类文件(kotlin实现)_第3张图片

至此,过程全部完成,生成的类可以直接去使用了。

你可能感兴趣的:(自定义注解并生成类文件(kotlin实现))