Es esa época del año en el hemisferio norte: las hojas cambian de color, la temperatura refresca y la última versión estable del año ya está aquí. ¡Hola y bienvenido a Flutter 2.8! Esta versión representa el trabajo duro de 207 contribuyentes y 178 revisores, que produjeron 2424 peticiones de validación (PR) fusionadas y 2976 problemas resueltos. Queremos agradecer especialmente al contribuyente principal de la comunidad de esta versión, Bartosz Selwesiuk, un ingeniero de Flutter en Very Good Ventures, que proporcionó 23 PR, de las cuales la mayoría estuvieron "enfocadas" (cita textual) más que nada en el complemento de cámara para la Web.
Todo este trabajo colectivo produjo mejoras de rendimiento significativas, tanto en el motor como en Flutter DevTools: una versión estable del kit de desarrollo de software (SDK) de Google Mobile Ads para Flutter, una gran cantidad de funciones y mejoras nuevas de Firebase, WebView 3,0, un nuevo lote de paquetes de Flutter Favorite, una serie de actualizaciones de computadora de escritorio en el camino hacia una versión estable y una nueva versión de DartPad con compatibilidad para más paquetes, incluido el propio Firebase. Puede que este sea el último lanzamiento del año, pero de ninguna manera el menos importante. ¡Comencemos!
Como siempre, la prioridad número uno de Flutter es la calidad. Pasamos mucho tiempo asegurándonos de que Flutter se ejecute de la forma más fluida y robusta posible en todo el rango de dispositivos compatibles.
Esta versión incluye mejoras en la latencia de inicio de apps. Probamos estas mejoras en Google Pay, una app popular de gran tamaño con más de un millón de líneas de código para asegurar que estos cambios generen un impacto perceptible en el mundo real. En conjunto, estas mejoras han generado una reducción del 50% en la latencia de inicio de Google Pay cuando se ejecuta en un dispositivo Android poco sofisticado y una mejora del 10% en dispositivos de alta gama.
Gracias a las mejoras en la manera en que Flutter influye en la política de recolección de elementos no utilizados de la VM de Dart, ahora se pueden evitar ciclos de recolección de elementos no utilizados (GC) inoportunos durante la secuencia de inicio de la app. Por ejemplo, antes de que se renderice el primer fotograma en Android, Flutter ahora solo envía notificaciones a la VM de Dart sobre exigencia de memoria para señales TRIM_LEVEL_RUNNING_CRITICAL y posteriores. En las pruebas locales, este cambio disminuyó el tiempo para el primer fotograma hasta 300 ms en un dispositivo poco sofisticado.
Debido a un exceso de precaución, en versiones anteriores, Flutter bloqueaba el subproceso de la plataforma mientras generaba visualizaciones de la plataforma. En el análisis y razonamiento cuidadoso, se determinó que se podía quitar parte de la serialización, lo que quitó más de 100 ms de bloqueo durante el inicio de Google Pay en un dispositivo poco sofisticado.
En el pasado, la configuración del administrador de fuente predeterminada generaba un retraso artificial en la configuración del primer elemento aislado de Dart. El retraso en la configuración del administrador de fuente predeterminada para que se ejecute de forma simultánea con la configuración del elemento aislado de Dart mejoró la latencia de inicio e hizo que los efectos de las optimizaciones anteriores sean mucho más visibles, ya que esto era el cuello de botella principal.
Los desarrolladores de Flutter que trabajaban con dispositivos que tenían restricciones de memoria tenían problemas con los registros del rendimiento debido a que Flutter cargaba con rapidez el "elemento aislado del servicio" de la VM de Dart, cuyo código AOT estaba unido a la app de manera que Flutter leía a ambos en la memoria al mismo tiempo. Para Android en la versión 2.8, se dividió el elemento aislado del servicio de la VM de Dart en su propio conjunto que se puede cargar por separado, lo que da como resultado ahorros de memoria de hasta 40 MB hasta que se necesite el elemento aislado del servicio. Se redujo aún más el consumo de memoria hasta un 10% mediante la VM de Dart que informa al SO que las páginas de la memoria utilizadas por el programa AOT están respaldadas por un archivo que es probable que no se necesite leer de nuevo. Por lo tanto, las páginas que tenían una copia de los datos respaldados por el archivo se pueden recuperar y destinar a otros usos.
En ocasiones, los desarrolladores desean ver los datos de registro de rendimiento de Flutter junto con los eventos de seguimiento nativos de Android. Además, a veces desean ver eventos de registro incluso en compilaciones en modo de lanzamiento a fin de comprender mejor los problemas de rendimiento en sus apps implementadas. Con ese propósito, la versión estable 2.8 ahora envía eventos de seguimiento al registrador de Systrace de Android si está habilitado en el inicio de la app, y estos eventos se envían incluso cuando la app de Flutter se compila en modo de lanzamiento.
También, para ayudar a crear animaciones con menos bloqueo, algunos de ustedes querían recibir más información en los registros de seguimiento sobre el comportamiento del caché de trama, lo que permite a Flutter copiar imágenes costosas reutilizadas en lugar de volver a dibujarlas en cada fotograma. Los nuevos eventos de flujo en los registros de seguimiento ahora permiten rastrear las vidas útiles de las imágenes de caché de trama.
Para la depuración de problemas de rendimiento, esta versión de DevTools agrega una nueva función de "mejora de seguimiento" para ayudarte a diagnosticar bloqueos de IU que surgen de operaciones costosas de compilación, diseño y pintura.
Cuando se habilita cualquiera de estas funciones de seguimiento, el cronograma incluye nuevos eventos para widgets compilados, objetos de renderización diseñados y objetos de renderización pintados, según corresponda.
Además, esta versión de DevTools agrega una nueva compatibilidad para la creación de perfiles del rendimiento del inicio de tu app. Este perfil contiene muestras de CPU desde la inicialización de la VM de Dart hasta la renderización del primer fotograma de Flutter. Luego de presionar el botón de "Perfil de inicio de app" y después de que se haya cargado el perfil de inicio de la app, verás que la etiqueta de usuario "AppStartUp" está seleccionada para el perfil. También puedes cargar el perfil de inicio de la app mediante la selección de este filtro de etiqueta de usuario, si está presente, en la lista de etiquetas de usuario disponibles. La selección de esta etiqueta muestra tus datos de perfil para el inicio de tu app.
Android y iOS no son las únicas plataformas con mejoras del rendimiento. Esta versión también mejora el rendimiento de las vistas de plataforma de la web de Flutter. Si no estás familiarizado con las vistas de plataforma, estas son las maneras en que Flutter permite alojar componentes de IU nativos desde la plataforma subyacente en tu app. La web de Flutter implementa esto mediante el widget HtmlElementView, que permite alojar elementos HTML dentro de tu app web de Flutter. Si utilizas las versiones web del complemento google_maps_flutter o del complemento video_player, o si sigues el consejo del equipo de Flutter sobre cómo optimizar las imágenes de la pantalla en la Web, entonces utilizas las vistas de plataforma.
En versiones anteriores de Flutter, la incorporación de una vista de plataforma creaba un lienzo nuevo de forma inmediata, y cada vista de plataforma adicional agregaba otro lienzo. Es costoso crear lienzos adicionales, ya que cada uno tiene el tamaño de toda la ventana. Esta versión reutiliza lienzos creados para vistas de plataforma anteriores, por lo que, en lugar de incurrir en el costo 60 veces por segundo, incurres en el costo una vez en toda la vida útil de la app. Esto significa que puedes tener varias instancias HtmlElementView en tus apps web sin degradar el rendimiento, mientras reduces el bloqueo de desplazamiento cuando se utilizan las vistas de plataforma.
Flutter no solo implica el marco de trabajo, el motor y las herramientas: hay más de 20 000 paquetes y complementos compatibles con Flutter en pub.dev y se agregan más cada día. Una parte significativa de las interacciones que los desarrolladores de Flutter tienen día tras día forma parte del ecosistema más amplio, así que veamos lo que ha estado sucediendo en el ecosistema de Flutter desde la versión anterior.
En primer lugar, la versión del SDK de Google para móviles para Flutter tiene disponibilidad general en noviembre.
Esta versión es compatible con 5 formatos de anuncios, integra compatibilidad para AdMob y Ad Manager e incluye una versión beta de una nueva función de mediación para ayudarlo a optimizar el rendimiento de los anuncios. Para obtener más información sobre la integración de Google Ads en tu app de Flutter y otras opciones de monetización, consulta la nueva página de monetización en flutter.dev.
Otro nuevo lanzamiento que viene con Flutter en esta ocasión es la versión 3.0 del complemento webview_flutter. Hemos incrementado el número de versión debido a la cantidad de funciones nuevas, pero también debido a un posible cambio rotundo en la manera en que funcionan las vistas web en Android. En versiones anteriores de webview_flutter, estaba disponible el modo de composición híbrida, pero no el modo predeterminado. Mediante la composición híbrida, se arreglan ciertos problemas que tiene el modo de visualizaciones virtuales predeterminado anterior. Según los comentarios de los usuarios y el rastreo de problemas, creemos que es hora de que la composición híbrida se convierta en la opción predeterminada. Además, webview_flutter también agrega varias funciones muy solicitadas:
Además, en la versión 3.0, webview_flutter proporciona compatibilidad preliminar para una nueva plataforma: la Web. Muchos de ustedes pidieron la capacidad de alojar WebView en una app web de Flutter, lo que permite compilar una app para dispositivos móviles o la Web de una única base de código. ¿Cómo luce el alojamiento de WebView en una app web de Flutter? Bueno, desde una perspectiva de programación, luce exactamente igual:
Cuando se ejecuta en la Web, funciona de la manera esperada:
Ten en cuenta que la implementación actual de webview_flutter para la Web tiene algunas limitaciones, con base en el hecho de que está compilado con iframe, que solo admite cargas de URL simples y no tiene capacidad de controlar o interactuar con el contenido cargado (para obtener más información, consulta el archivo README de webview_flutter_web). Sin embargo, estamos tratando de que webview_flutter_web esté disponible como un complemento no aprobado debido a la gran demanda. Si deseas probarlo, agrega la siguiente línea a tu pubspec.yaml:
Si tienes comentarios sobre webview_flutter v.3.0, ya sea en la Web o fuera de esta, regístralos en el repositorio de Flutter como un problema de WebView. Además, si no has utilizado WebView antes o te gustaría ver un repaso, consulta el nuevo codelab de WebView, que te guía paso por paso a través del proceso de alojamiento de contenido web en tu app de Flutter.
El Comité del ecosistema de Flutter se ha reunido de nuevo para designar lo siguiente como paquetes de Flutter Favorite:
Felicitamos a esos creadores de paquetes y les agradecemos por apoyar a la comunidad de Flutter con su trabajo duro. Si estás interesado en nominar a tu paquete de Flutter favorito para que reciba un premio de Flutter Favorite, sigue las guías e instrucciones en la página del programa Flutter Favorite.
Si eres creador de paquetes, una decisión que debes tomar es qué plataformas vas a admitir. Si compilas un complemento con un código nativo para plataformas específicas, puedes hacerlo con la propiedad pluginClass en el pubspec.yaml de tu proyecto, que indica la clase nativa que proporciona la funcionalidad:
Sin embargo, a medida que la interfaz de funciones foráneas (FFI) de Dart se vuelve más madura, es posible implementar la funcionalidad para plataformas específicas en Dart al 100%, como lo hace el paquete path_provider_windows. Cuando no tienes ninguna clase nativa para utilizar, pero aún deseas designar tu paquete para que admita solo ciertas plataformas, utiliza la propiedad dartPluginClass en su lugar:
Con esta configuración implementada, has designado a tu paquete para que solo admita ciertas plataformas, incluso si no tienes ningún código nativo. También debes proporcionar la clase de complemento de Dart; obtén más información en los documentos sobre implementaciones de plataformas solo en Dart en flutter.dev.
Otra parte importante del ecosistema de Flutter es FlutterFire, que se utiliza en dos tercios de apps de Flutter. Esta versión agrega un conjunto de funciones nuevas que facilitan la compilación de apps con Flutter y Firebase:
Todos (o casi todos) los complementos de FlutterFire han dejado de ser versiones beta para pasar a ser versiones de calidad estable.
Entre los complementos que pasan a ser versiones estables para Android, iOS y la Web, se incluyen Analytics, Dynamic Links, In-App Messaging, Performance Monitoring, Realtime Database, Remote Config y, el recién llegado, Installations. El complemento App Check y la compatibilidad para plataformas macOS todavía se encuentran en versiones beta debido a la fase de las propias bibliotecas de Firebase, que también están en versiones beta. Si te has preocupado por elegir Realtime Database, Analytics o Remote Config porque las bibliotecas de FlutterFire no estaban listas para hacerse públicas, ya no te preocupes. Ahora estos son complementos totalmente compatibles listos para usar en la producción.
A medida que los paquetes se han trasladado a la calidad de producción, hemos agregado la capacidad de inicializar Firebase en cualquier plataforma compatible de Dart:
Este código inicializa una app de Firebase mediante las opciones adecuadas para cada plataforma compatible, como se define en el archivo firebase_options.dart, que contiene estructuras de datos según plataformas que tienen el siguiente aspecto:
A fin de recolectar los datos para cada estructura de datos de la opción de inicialización de cada plataforma, consulta la nueva herramienta de la CLI de FlutterFire.
Esta herramienta analiza los datos en tus subcarpetas de plataformas específicas para encontrar la ID de conjunto única y, luego, la utiliza con el fin de buscar los detalles específicos del proyecto de Firebase para tus apps de plataformas específicas compatibles e incluso crea nuevas apps para plataformas específicas o un nuevo proyecto de Firebase si no había ninguno. Lo que esto significa es que ya no necesitarás descargar y agregar un archivo json a tu proyecto de Android, descargar y agregar un archivo plist a tus proyectos de iOS y macOS ni pegar código en el index.html de tus proyectos web; sin importar con qué plataforma compatible con Firebase estés trabajando, este único fragmento de código Dart inicializa Firebase para tu app. Ten en cuenta que puede que esta no sea la única inicialización que tengas que realizar para hacer funcionar tu app de FlutterFire; por ejemplo, puede que desees integrar la creación de tus símbolos de Crashlytics en tu compilación Android o compilación iOS, pero debería ponerse en marcha en minutos con cualquier proyecto nuevo de Firebase.
Con esta inicialización de FlutterFire solo en Dart, ahora puedes utilizar Firebase desde dentro de DartPad.
En este ejemplo, se demuestra una pequeña app de chat con Flutter, Firebase y DartPad, los que puedes utilizar ahora mismo sin instalación. En la compatibilidad para Firebase de DartPad actual, ya se incluyen las API principales, la autenticación y Firestore. Se espera que surjan más servicios de Firebase en DartPad con el tiempo.
Otra función que la compatibilidad de FlutterFire en DartPad habilita es la capacidad de utilizar una instancia incorporada de DartPad en los documentos.
En este ejemplo, estás viendo los documentos de Cloud Firestore con el código para la app de ejemplo que puedes ejecutar y editar directamente en tu navegador sin tener que instalar nada, crear un proyecto de prueba o incluso copiar o pegar el código. Todo está allí para que lo utilices de forma inmediata.
Cuando se integra Firebase en una app, la mayoría de las apps tienen algún tipo de flujo de autenticación. Esto incluye permitir que los usuarios inicien sesión con un correo electrónico y una contraseña o con un proveedor de autenticación social como el que proporciona Google. Firebase Authentication también permite crear cuentas nuevas sobre la marcha, validar direcciones de correo electrónico, cambiar contraseñas, y hasta puede implicar la verificación de 2 pasos con SMS, iniciar sesión con un número de teléfono o hasta combinar varias cuentas de usuario en una sola cuenta. Firebase Authentication admite todas estas funcionalidades, pero, como desarrollador de Flutter, eres responsable de implementar la IU para todas ellas. Así era hasta hoy.
Hoy estamos felices de anunciar que el paquete flutterfire_ui puede crear una experiencia de autenticación básica con una pequeña cantidad de código. Como ejemplo, asume que tienes configurada la autenticación por correo electrónico y la de Google en tu proyecto de Firebase:
Con esta configuración, puedes activar una experiencia de autenticación de la siguiente manera:
Esto inicializa Firebase y, cuando se observa que el usuario todavía no ha iniciado sesión, se muestra la pantalla de inicio de sesión. El widget SigninScreen se configura mediante los proveedores de autenticación de correo electrónico y Google. El código también escucha el estado de autenticación del usuario con el paquete firebase_auth, de manera que, una vez que el usuario inicie sesión, puedes mostrar el resto de la app. Con este código, obtienes un inicio de sesión en funcionamiento para todas las plataformas admitidas por Firebase: Android, iOS, Web y macOS.
Con un poco más de configuración, puedes agregar de forma fácil una imagen y algo de texto personalizado (los detalles están disponibles en los documentos), lo que te da una experiencia de inicio de sesión repleta de funciones.
En esta captura de pantalla se muestra la versión para dispositivos móviles, pero, como las pantallas de flutterfire_ui son adaptables, esto es lo que ves en un dispositivo de escritorio:
Si el usuario ya tiene un correo electrónico o una contraseña, puede iniciar sesión y terminar. Si utiliza la autenticación de Google, se le mostrará el flujo de autenticación normal de Google, ya sea si utiliza un dispositivo móvil, la Web o la computadora. Si no tiene una cuenta todavía, puede presionar el botón en la pantalla de inicio de sesión e ir a la pantalla de registro. Una vez que el usuario haya iniciado sesión o se haya registrado, hay flujos para validar su correo electrónico, cambiar la contraseña, cerrar sesión y vincular cuentas de autenticación social. El inicio de sesión por correo electrónico funciona en todas las plataformas junto con la compatibilidad para la autenticación social de Google, Facebook y Twitter y compatibilidad parcial para Apple (no funciona en Android). La compatibilidad de autenticación en flutterfire_ui admite varios escenarios y esquemas de navegación, junto con opciones de localización y personalización. Consulte las muestras y documentos detallados en los documentos de firebase.flutter.dev.
Además, la autenticación no es la única función de Firebase relacionada con IU compatible con flutterfire_ui. Para mostrarles a los usuarios una lista de datos desplazable, infinita y en vivo de una consulta de Firebase, esta versión incluye la función FirestoreListView, que puedes incorporar en tu app con una consulta en vivo de la siguiente manera:
Y así luce cuando está en funcionamiento:
O, si te gustaría ofrecer a tus usuarios la capacidad de crear, leer, actualizar y borrar entradas en una tabla, ya tienes lo básico en FirestoreDataTable:
Que funciona de la siguiente manera:
Para obtener detalles sobre autenticación, vistas de lista y tablas de datos, consulta los documentos de flutterfire_ui. Como esta es una versión preliminar, se prevén funciones adicionales. Si tienes alguna duda o una solicitud de función, dirígete al repositorio de GitHub para registrar problemas o preguntar dudas en la sección de discusiones.
Y por último, aunque no menos importante, una nueva función de la integración entre Firebase y Flutter que deberías conocer es la versión alfa del asignador de objetos/documentos de Firestore. El ODM de Firestore está orientado a ayudar a los desarrolladores de Flutter a ser más productivos mediante la simplificación del uso de Firestore a través de objetos y métodos estructurados familiares de tipo seguro. Mediante la generación de código, el ODM de Firestore mejora la sintaxis para interactuar con documentos y colecciones y te permite modelar tus datos de forma segura:
Con estos tipos en funcionamiento, ahora puedes ejecutar consultas de tipo seguro:
El ODM también admite la definición de subcolecciones de asignación rigurosa y proporciona opciones incorporadas para optimizar recompilaciones de widget con su función selecta. Puedes leer acerca de todo esto y mucho más en los documentos sobre el ODM de Firestore. Como esta es una versión alfa, proporciónanos tus comentarios. Para enviar comentarios y preguntar dudas, únete al hilo sobre ODM de Firestore en la discusión de FlutterFire.
En la versión 2.8 de Flutter, se incluye otro gran paso en el camino hacia la versión estable de Windows, macOS y Linux. El estándar de calidad es alto, incluida la compatibilidad con internacionalización y localización, como la compatibilidad con IME china, la compatibilidad con IME coreana y la compatibilidad con IME de kanji recién lanzadas. O como la integración sólida que se está incorporando en la compatibilidad de accesibilidad de Windows. No es suficiente que Flutter se ejecute en computadoras de escritorio en el canal estable (algo que ya hace en la versión beta detrás de una marca), tiene que ejecutarse de forma correcta para lenguajes y culturas alrededor del mundo y para personas con distintos tipos de capacidades. Todavía no funciona como queremos, ¡pero lo estamos logrando!
Un ejemplo del trabajo continuo a fin de preparar a las computadoras de escritorio para una versión estable es el cambio de arquitectura completo de cómo Flutter administra eventos de teclado para permitir una respuesta síncrona. Esto habilita a un widget a administrar una pulsación de tecla y cancelar su propagación a través del resto del árbol. El trabajo inicial incorporado en Flutter 2.5 y Flutter 2.8 agrega correcciones para problemas y regresiones a medida que se aproxima a la calidad estable. Esto se suma al trabajo continuo para renovar la forma en que administramos la entrada del teclado de dispositivos específicos y una refactorización de la manera en que Flutter administra la edición de texto, todas funciones necesarias para las apps de computadora de escritorio con teclado de gran entrada.
Además, continuamos ampliando la compatibilidad de Flutter para la densidad visual y la alineación de exposición de los diálogos, ambas para habilitar una IU más compatible con la computadora de escritorio.
Y, finalmente, el equipo de Flutter no es el único que trabaja en la computadora de escritorio de Flutter. Solo como un ejemplo, el equipo de computadoras de escritorio de Canonical está trabajando con Invertase en una implementación de los complementos de Firebase más populares para Flutter en Linux y Windows.
Puedes leer más sobre la versión preliminar en el blog de Invertase.
Una versión de Flutter no está completa sin analizar las mejoras de herramientas. Esta publicación se enfoca en las mejoras de DartPad, de las cuales la mayor admite una gran cantidad de paquetes. De hecho, hay 23 paquetes disponibles para importación. Además de varios servicios de Firebase, la lista incluye paquetes populares como bloc, characters, collection, google_fonts y flutter_riverpod. El equipo de DartPad continúa agregando nuevos paquetes, así que si deseas ver qué paquetes se admiten actualmente, haz clic en el ícono de información en la esquina inferior derecha.
Para conocer sobre el plan de agregar nuevos paquetes a DartPad con el transcurso del tiempo, consulta este artículo en el wiki de Dart.
También hay otra función nueva de DartPad que es muy útil. Anteriormente, DartPad siempre se ejecutaba en la última versión estable. Con esta versión, puedes seleccionar las versiones de canal beta más recientes como también la versión estable anterior (llamada el "canal antiguo") mediante el nuevo menú Canal en la barra de estado.
Esta opción puede ser muy útil si, por ejemplo, estás escribiendo una entrada de blog donde la versión estable más reciente no es lo suficientemente nueva…
Un "canal" de Flutter administra qué tan rápido el marco y el motor subyacentes de Flutter cambian en su máquina de desarrollo, y el canal estable representa la menor tasa de abandono y el maestro la mayor. Debido a restricciones de recursos, hace poco dejamos de actualizar el canal para desarrolladores. Aunque recibimos algunas preguntas acerca de esto, observamos que menos del 3% de los desarrolladores de Flutter utilizan el canal para desarrolladores. Por lo tanto, hemos decidido comenzar el proceso de quitar el canal para desarrolladores de manera formal. Aunque algunos desarrolladores utilizan el canal para desarrolladores, exige una cantidad considerable de tiempo y esfuerzo por parte de los ingenieros de Flutter para mantenerlo. Si pasas todo tu tiempo en el canal estable (como más del 90% de los desarrolladores de Flutter), no lo extrañarás. Si se quita, tienes una decisión menos por tomar, y el equipo de Flutter puede usar su tiempo y energía en otras cosas.
Puedes decidir qué canal te gustaría utilizar mediante el comando de canales de Flutter. A continuación, se describe lo que el equipo de Flutter piensa sobre cada canal:
A medida que quitamos el canal para desarrolladores en los próximos meses, considera los canales beta o maestro según tu tolerancia a la tasa de abandono y tu necesidad de mantenerte actualizado.
Como siempre, nos esforzamos por reducir la cantidad de cambios rotundos en cada versión. En esta versión, Flutter 2.8 no presenta cambios rotundos, además de las API obsoletas que han expirado y se han quitado según nuestra política de cambios rotundos.
Si todavía utilizas estas API y te gustaría obtener detalles sobre cómo actualizar tu código, puedes leer la guía de migración en flutter.dev. Como siempre, agradecemos a la comunidad por contribuir con pruebas que nos ayudan a identificar estos cambios rotundos.
A medida que despedimos el 2021 y esperamos con ansias el 2022, el equipo de Flutter quiere expresar nuestra gratitud por el trabajo y la asistencia de toda la comunidad de Flutter. Aunque es cierto que compilamos Flutter para la cantidad en aumento de desarrolladores del mundo, también es cierto que no podríamos compilarlo sin ti. La comunidad de Flutter es diferente a cualquier otra, y estamos agradecidos por eso. ¡Te deseamos unas felices vacaciones y nos vemos el año próximo!