Lo que MENOS me gusta de Flutter son "Las Actualizaciones" + Consejos

- Andrés Cruz - EN In english

Video thumbnail

Lo que me molesta mucho sobre el ecosistema de Flutter es Android, las benditas actualizaciones.
 

Tengo la compulsión de mantener todo actualizado y corro comandos varias veces por semana. Mantengo SDKs, paquetes y Android Studio al día. El detalle es que de un día para otro un proyecto que funcionaba deja de hacerlo.

flutter upgrade

entre otros.

Por ejemplo, en Windows un proyecto de la academia me corría perfecto, pero en MacOS no. Antes era al revés: en Mac funcionaba y en Windows no. Y todo esto solo por diferencias de versiones y actualizaciones.

Errores, versiones, dependencias y +

  • Estos problemas suelen venir acompañados de errores muy verbosos. Por ejemplo, en Windows tuve un conflicto con un paquete (WYSIWYG editor), que luego actualizaron. También me ha pasado con el SDK de Android: versiones 35 y 36 causando advertencias y fallos.
  • Muchas veces no se entiende qué está pasando. Termino rastreando archivos, revisando dependencias internas del proyecto, como archivos gradle principalmente, versionamientos con el android SDK o el Flutter SDK o el pubspec.yaml o .lock.
  • Sin contar que internamente van actualizando el proyecto en Android con otras sintaxis o directamente tipado de los archivos, un ejemplo de esto ultimo es el build.gradle.kts cuya extensión para Kotlin, kts en versiones más antiguas, no venia incluida.

Es muy molesto porque no son proyectos “antiguos”, sino relativamente recientes. Pero las actualizaciones los vuelven incompatibles. Y aquí aparece el dilema:

  • O intentas actualizar manualmente, rezando para no olvidar nada.
  • O creas un proyecto nuevo en Flutter y empiezas a copiar/pegar todo, con el riesgo de dejar algo fuera (como me pasó una vez con el AndroidManifest).
  • Por eso pienso que debería existir un comando que actualice proyectos automáticamente. Hacerlo a mano es fastidioso y consume demasiado tiempo.

Entonces en conclusion, el problema de Flutter no es la codificación o el lenguaje de programación, el veneno lo lleva internamente el mismo proyecto, al no actualizarse automáticamente a medida que se van lanzando nuevas actualizaciones sobre las technologies relacionadas.

La forma inteligente de actualizar Flutter sin romper tu aplicación

Video thumbnail

Uno de los puntos más críticos al trabajar con Flutter radica en la gestión de sus actualizaciones. Aunque es un framework robusto, la evolución de sus versiones suele acarrear problemas de compatibilidad que pueden romper un proyecto existente. Este fenómeno no es exclusivo de Flutter; frameworks de backend como Laravel también enfrentan desafíos similares debido a su rápida evolución, provocando desajustes en aplicaciones que quedan desactualizadas.

Para comprender la raíz de este problema en Flutter, es fundamental analizar su arquitectura interna. Flutter permite desarrollar un único código base en Dart y exportarlo de forma nativa a múltiples plataformas: Android, iOS, Web y entornos de escritorio (Windows, Linux y macOS). Por esta razón, la estructura de un proyecto incluye carpetas dedicadas a cada sistema operativo (/android, /ios, /web, etc.). Estas carpetas no son meros contenedores; albergan los entornos nativos necesarios para la compilación final.

La Dependencia de Entornos Nativos

Debido a esta arquitectura, Flutter depende obligatoriamente de las herramientas específicas de cada plataforma para compilar el código nativo:

  • Android: Requiere Android Studio, su SDK, Command Line Tools y Gradle.
  • iOS: Requiere Xcode y las herramientas de desarrollo de Apple.
  • Windows: Requiere módulos específicos de Visual Studio (C++).

El verdadero conflicto surge porque estas plataformas nativas evolucionan de forma independiente a Flutter. Tomando como ejemplo a Android, el sistema operativo actualiza constantemente sus niveles de SDK, versiones de Java y herramientas de compilación. Cuando se actualiza el SDK de Flutter mediante el comando flutter upgrade, es muy probable que se rompa la sincronización con el entorno nativo subyacente.

El Rol Crítico de Gradle en Android

En el ecosistema de Android, la configuración y el éxito de la compilación dependen principalmente de tres archivos gestionados por Gradle. Cuando un proyecto tiene varios meses o años de antigüedad, las versiones de estos archivos entran en conflicto con las directrices del nuevo SDK de Flutter:

  1. build.gradle (Raíz del proyecto Android): Define los repositorios y las versiones globales de los plugins de Gradle.
  2. build.gradle (Directorio /app): Especifica las versiones de compileSdkVersion, minSdkVersion y targetSdkVersion.
  3. gradle-wrapper.properties: Determina la versión exacta del motor de Gradle que descargará el sistema para compilar.

Históricamente, resolver estos conflictos requería un proceso de ensayo y error tedioso: buscar compatibilidades de versiones en repositorios oficiales, limpiar la caché del proyecto mediante flutter clean o ejecutar comandos nativos como gradlew clean. Además, los cambios sintácticos introducidos en las herramientas de compilación —como la transición de archivos de configuración tradicionales basados en Groovy hacia el formato moderno KTS (Kotlin Script)— elevan la complejidad del mantenimiento manual.

Antiguo:

android/build.gradle

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.buildDir = '../build'

Moderno:

android/build.gradle.kts

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)

Estrategias de Solución y Mitigación

Para resolver estas desincronizaciones sin comprometer la estabilidad del desarrollo, se pueden aplicar tres enfoques estratégicos:

A. Diagnóstico asistido por Inteligencia Artificial

Actualmente, el uso de modelos de lenguaje facilita la resolución de errores de compilación verbosos. Al proporcionar el log completo del error generado por Gradle a la IA, esta suele identificar con precisión la incompatibilidad exacta y sugerir los rangos de versiones correctos para los archivos de configuración.

B. Regeneración Selectiva de la Carpeta Nativa (Enfoque Recomendado)

A menos que se esté implementando código nativo a medida, la carpeta /android no suele modificarse manualmente, salvo por configuraciones en el archivo AndroidManifest.xml (permisos de internet, llaves de AdMob, servicios de notificaciones, etc.). Por lo tanto, una solución eficiente consiste en sustituir la estructura nativa obsoleta por una limpia:

  • Asegurar los cambios actuales realizando un git commit o copia de seguridad.
  • Renombrar la carpeta /android conflictiva (por ejemplo, a /android_old) para conservarla como referencia.
  • Generar un nuevo proyecto de Flutter en un directorio temporal utilizando el mismo nombre de paquete (Package Name) para heredar la carpeta /android actualizada y compatible con el nuevo SDK.
  • Copiar esta carpeta limpia al proyecto original y migrar únicamente las líneas de configuración específicas (como los permisos del AndroidManifest.xml) desde la carpeta antigua.

C. Migración Completa a un Proyecto Espejo

Si la sustitución de carpetas genera conflictos de dependencias persistentes, la solución definitiva consiste en crear un proyecto completamente nuevo desde cero. Posteriormente, se realiza la migración manual del directorio de código fuente principal (/lib) y las declaraciones de dependencias dentro del archivo pubspec.yaml, garantizando así un entorno de compilación totalmente depurado.

Una de las cosas mas molestas del ecosistema de Flutter, son las actualizaciones de Flutter, paquetes del proyecto perce que pueden ROMPER nuestro proyecto.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

Acepto recibir anuncios de interes sobre este Blog.