Es posible que haya desarrollado muchos proyectos, pero no ha escrito tanto código gradle. Eso puede pasar. La parte que nos interesa para nuestro propósito es la generación de tiempo. A ella le gusta mucho la biblioteca, sabes el enlace de datos, daga, viejo amigo Cuchillo de mantequilla (RIP) utiliza la generación de código de tiempo de compilación. Eso es lo que vamos a hacer. Así que dividí la parte del complemento en tres partes pequeñas. Puede pensar en ellos como piezas de automóvil.
Primer componente: extensión del complemento (llave del automóvil)
Lo primero que quiero es tomar el archivo JSON desde el exterior y luego procesarlo correctamente. Debido a que somos parte de un complemento, necesitamos crear una clase para extender el complemento. No se preocupe, es solo una clase modelo simple.
public class StringGeneratorExtension {public static final String NAME = "stringGenerator";
private File stringsJsonFile;
public File getStringsJsonFile() {
return stringsJsonFile;
}
@InputFile
public void setStringsJsonFile(@Nullable File stringsJsonFile) {
this.stringsJsonFile = stringsJsonFile;
}
}
Entonces, si alguna vez ha usado un complemento, probablemente haya visto algo así antes. Puede pensar en las dependencias como una clase de extensión y una palabra clave de implementación como una variable.
Así que básicamente estamos haciendo lo mismo. Si usa nuestras extensiones, tiene algo similar. Ambos son legales.
Segunda parte: el papel del complemento (motor de automóvil)
Esta es la parte en la que hacemos la mayor parte del trabajo. Puede pensar en esta pieza como un motor de automóvil. Así que mencionaré sus pequeñas partes. Y luego vemos la luz del sol.
Bien, dijimos que queríamos un archivo JSON. Logramos tomarlo del desarrollador dentro de la extensión de gradle. Y lo que vamos a hacer es romper JSON en pedazos. Usé otro viejo amigo gson fácil de hacer. Aquí hay un JSON POJO simple.
/*
{
"string" : {
"true_music": "Long live heavy metal",
"my_repo": "https://github.com/volsahin",
"description" : "String generator plugin",
"done" : "done"
}
}
*/public class StringsJsonEntity {@SerializedName("string")
private Map<String, String> strings;public Map<String, String> getStrings() {
return strings;
}
}
Por tanto, el análisis de piezas es sencillo.
@Nullable
private StringsJsonEntity createStringsJsonEntity() {
try {
JsonReader reader = new JsonReader(new FileReader(extension.getStringsJsonFile()));
return new Gson().fromJson(reader, StringsJsonEntity.class);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
Ahora hemos analizado nuestro JSON en nuestro modelo. Y sabemos que queremos generar una clase con esta información. Gracias a nuestros amigos de la plaza, facilítalo porque hacen un uso intensivo de la generación de clases en sus proyectos. Puedes comprobar https://github.com/square/javapoet para su uso.
Primero creamos nuestra clase R. Pero en nuestro caso es la clase RR. Por qué no? Entonces, para generar una clase llamada RR, debe hacer algo similar
private static final String RESOURCE_CLASS_NAME = "RR";@TaskAction
public void execute() {
TypeSpec.Builder resourceClass = createResourceClass();
}private TypeSpec.Builder createResourceClass() {
return TypeSpec.classBuilder(RESOURCE_CLASS_NAME)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
}
Está bien, tenemos una clase RR con nosotros. Aún no hemos creado al creador, pero pensamos que es de la forma en que él ya lo creó. Entonces quiero otra clase llamada cadena. Cuando usa strings.xml, llama a sus cadenas como R.string.megadeth, por lo que creamos nuestra clase RR.string.
private static final String STRING_CLASS_NAME = "string";@TaskAction
public void execute() {
TypeSpec.Builder resourceClass = createResourceClass();
TypeSpec.Builder stringClass = createStringClass();
}private TypeSpec.Builder createStringClass() {
return TypeSpec.classBuilder(STRING_CLASS_NAME)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
}
Luego queremos leer todos los pares clave-valor de la cadena y ponerlos como variables en la clase de cadena para llegar a ellos como RR.string.mustaine.
@TaskAction
public void execute() {
TypeSpec.Builder resourceClass = createResourceClass();
TypeSpec.Builder stringClass = createStringClass();
createKeyValueVariablesInClass(stringClass);
resourceClass.addType(stringClass.build());
}
Por último, pero no menos importante, necesitamos generar nuestro archivo. Es una parte fácil si sabe dónde generarla. Mencionaré esto en la siguiente sección, para que pueda generar dicho archivo. Aquí también imprimo la clase al terminal.
private void generateStringResourceFile(TypeSpec.Builder classBuilder) {
final JavaFile javaFile = JavaFile.builder(FILE_PACKAGE_NAME, classBuilder.build()).build();
try {
javaFile.writeTo(new File(generationPath));
javaFile.writeTo(System.out);
} catch (IOException e) {
e.printStackTrace();
}
}
Nunca pensé que escribir una publicación intermedia fuera tan agotador. Así que es hora de jugar a Megadeth.
Tercer componente: complemento (el propio automóvil)
Bueno, en esta sección, es difícil determinar la ruta del archivo generado. Generar es fácil, pero si no lo genera en la carpeta correcta, no puede usar la clase en su código. Sorprendentemente, esa fue la parte en la que pasé la mayor parte del tiempo, y aquí están las cosas que puedo encontrar. Si es vago, puede agregar una clase de archivo generada a los conjuntos de fuentes del proyecto. Pero sera como leer código(Este es un idioma turco que creé, es decir, escribir código a ciegas solo para completar su trabajo y no estar interesado en las mejores prácticas) Entonces necesitas generar un archivo dentro construir / generar / fuente. Pero no olvide las variantes. En Android tenemos variantes como debug, release o lo que quieras. Por lo tanto, si está utilizando una variante de depuración, su código debe estar en construir / generar / fuente / depurar. Bien, aquí está el código del complemento.
Entonces ahora tiene nuestro complemento. Crea dos tareas llamadas generateStringResourceFileDebug y generateStringResourceFileRelease. Cuando complete estas tareas o simplemente cree su proyecto, verá su rostro orgulloso cuando se mire en el espejo.