Flujo de ejecución C. Ejemplos D. K in KAPT 2. Introducción a Kotlin Plugins A. Usos y Ejemplos B. Flujos de ejecución C. Deep dive: Android Extension Plugin 3. ¿Cuándo usar cada uno? EXTRA: KAPT y Plugins en el contexto de Kotlin/JS
Cada procesador se encarga de procesar las anotaciones que necesite UsuarioDao.class Usuario.class UsuarioTable.class UsuarioDao.java Usuario.java UsuarioTable.java 3. Cuando no queden más anotaciones por procesar, se termina
encarga de procesar las anotaciones que necesite 3. Cuando no queden más anotaciones por procesar, se termina Annotation Processing Boilerplate Destruction - Jake Wharton (droidconNYC 2014)
"()Ljava/util/List;", “main"} ) public final class Usuario { @NotNull private final List permisos; @NotNull public final List getPermisos() { return this.permisos; } public Usuario(@NotNull List permisos) { Intrinsics.checkParameterIsNotNull(permisos, "permisos"); super(); this.permisos = permisos; } }
0, 3}, k = 1, d1 = {"\u0000\u0016\n\u0002\u0018\..."}, d2 = {"Lcom/example/Usuario;", "", "permisos", "", "", "(Ljava/util/List;)V", "getPermisos", "()Ljava/util/List;", “main"} ) public final class Usuario { @NotNull private final List permisos; @NotNull public final List getPermisos() { De aqui podemos sacar más data!
v.invokeinterface("getContainerView") v.invokevirtual("findViewById") } // Should never occur else -> throw IllegalStateException("Invalid type") } public interface LayoutContainer { /** Returns the root holder view. */ public val containerView: View? }
v.invokeinterface("getContainerView") v.invokevirtual("findViewById") } // Should never occur else -> throw IllegalStateException("Invalid type") } *Only works if you enable* androidExtensions { experimental = true }
?: "" if (isWidgetTypeIgnored(localName)) { tag?.acceptChildren(this) return } val idAttribute = tag?.getAttribute(ID_ATTRIBUTE) if (idAttribute != null) { val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue) 1. Evaluates each <XML tag>
} override fun visitXmlTag(tag: XmlTag?) { val localName = tag?.localName ?: "" if (isWidgetTypeIgnored(localName)) { tag?.acceptChildren(this) return } val idAttribute = tag?.getAttribute(ID_ATTRIBUTE) if (idAttribute != null) { val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue)
} override fun visitXmlTag(tag: XmlTag?) { val localName = tag?.localName ?: "" if (isWidgetTypeIgnored(localName)) { tag?.acceptChildren(this) return } val idAttribute = tag?.getAttribute(ID_ATTRIBUTE) if (idAttribute != null) { val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue)
?: "" if (isWidgetTypeIgnored(localName)) { tag?.acceptChildren(this) return } val idAttribute = tag?.getAttribute(ID_ATTRIBUTE) if (idAttribute != null) { val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue)
{ val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue) if (name != null) { elementCallback(name, xmlType, idAttribute) } } } 3. Only considers widgets with an ID
xmlType = tag.getAttribute(CLASS_ATTRIBUTE) ?.value ?: localName val name = androidIdToName(idAttributeValue) if (name != null) { elementCallback(name, xmlType, idAttribute) } } } tag?.acceptChildren(this) } } 5. We found a valid widget! Now to the next step...
(variantData in moduleData.variants) { val variant = variantData.variant.name for (layoutName in variantData.layouts) { val packageName = "$SYNTHETIC_PACKAGE.$variant.$layoutName" createPackageFragment(packageFqName) createPackageFragment(packageFqName + “.view") } } }
val variant = variantData.variant.name for (layoutName in variantData.layouts) { val packageName = "$SYNTHETIC_PACKAGE.$variant.$layoutName" createPackageFragment(packageFqName) createPackageFragment(packageFqName + “.view") } } }
(variantData in moduleData.variants) { val variant = variantData.variant.name for (layoutName in variantData.layouts) { val packageName = "SYNTHETIC_PACKAGE.$variant.$layoutName" createPackageFragment(packageFqName) createPackageFragment(packageFqName + “.view") } } }
val element = event.element if (element != null && event.code == PROPERTY_CHANGED && event.propertyName == "fileName") { if (checkIfLayoutFile(element)) { incModificationCount() return } } val xmlAttribute = findXmlAttribute(child) ?: return val name = xmlAttribute.name if (name != "android:id" && name != "class") return And is an XML layout (inside res/layout folder)
val element = event.element if (element != null && event.code == PROPERTY_CHANGED && event.propertyName == "fileName") { if (checkIfLayoutFile(element)) { incModificationCount() return } } val xmlAttribute = findXmlAttribute(child) ?: return val name = xmlAttribute.name if (name != "android:id" && name != "class") return Layout should be re-evaluated!
nuevos archivos, comunicarte con el IDE, etc. -Son multiplataforma -Demandan DEMASIADO trabajo -Documentación casi nula -Por ahora, solo hay plugins desarrollados por JetBrains -El código existe LUEGO de compilar… pero puede integrarse en tiempo real con el IDE