El año pasado, he estado escribiendo aplicaciones Flutter para iOS y Android de todos modos. Antes de eso, tenía y tengo 5 años de experiencia con Xamarin. Han sido 5 años maravillosos. Gracias a Xamarin y mi amor por este marco, en principio me mudé al campo de los desarrolladores, esta herramienta me ayudó a ganar mucho dinero, conocimiento y encontrar colegas maravillosos. Entonces, ¿por qué estoy escribiendo en Flutter ahora? Respuesta corta, porque Flutter cubre todas las necesidades del desarrollo multiplataforma.Un poco de historia
Corríjame si me equivoco, pero 2009 fue clave en muchos aspectos para el desarrollo móvil en general y el desarrollo multiplataforma en particular. En 2009, se lanzó el iPhone 3gs, que le permitió ejecutar aplicaciones de terceros desde la AppStore. Por primera vez, esta oportunidad apareció un año antes en el iPhone 3g, pero 3gs se ha convertido en un iPhone realmente masivo y "popular". Nuevamente, un año antes, en septiembre de 2008, Android se presentó al público y en 2009 muchos fabricantes de teléfonos comenzaron a probar Android para sus nuevos modelos de teléfonos. En la primavera de 2009, Nitobi presentó PhoneGap, un nuevo marco para crear aplicaciones multiplataforma basadas en HTML5, CSS y JS. En el mismo año, en septiembreXimian lanzó MonoTouch, que le permitió escribir aplicaciones iOS usando Mono y C #. En el mismo 2009, en diciembre, Rovio Entertainment lanzó un juego para iOS y, por un momento, Maemo, que en muchos aspectos marcó el comienzo de la industria de los juegos móviles: Angry Birds. El último ejemplo aquí no es accidental.El primer marco multiplataforma "para las personas" puede considerarse PhoneGap (desarrolladores de Qt, no arrojen piedras). Fue una idea maravillosa y muy obvia: llevar la web al mundo del desarrollo móvil. Para 2009, las capacidades de la web ya habían comenzado a extenderse más allá del navegador ( hello node.js), mientras que escribir aplicaciones web en JS era bastante sencillo. El segundo punto, no menos importante, es la representación de la interfaz de usuario. La forma en que se realiza el renderizado recae en el motor del navegador y todos estos motores siguen más o menos los estándares W3C para HTML, CSS y DOM. Cualquier desarrollador web que haya creado un sitio espera que su sitio se vea casiidéntico en cualquier navegador, en cualquier plataforma. Esto, en mi opinión, es el aspecto más importante de la web como plataforma abierta. ¿Por qué debería aprender un nuevo lenguaje / marco para dibujar la interfaz de usuario para cada una de las plataformas, si durante mucho tiempo existe un estándar para modelar la interfaz de usuario para diferentes navegadores?Después de eso, Cordova se separó de PhoneGap y de Ionic. Parece que este es un marco ideal, pero hubo 2 puntos: rendimiento e integración del sistema operativo. Uno de los objetivos principales o, si lo desea, los puntos de referencia de la aplicación, escritos en soluciones multiplataforma era su "natividad". Aquellos. Idealmente, el 100% de los usuarios deberían considerar que su aplicación multiplataforma es nativa. Y esto significa que debería verse como nativo, funcionar como nativo y tener toda la integración posible con el sistema operativo. Al principio, todos estos puntos para PhoneGap eran inalcanzables, las capacidades de los teléfonos inteligentes hace 10 años no eran suficientes para la representación de la interfaz de usuario de 60 fps, la integración con el sistema operativo era mínima. Ahora hay bastantes aplicaciones en Ionic que son difíciles de distinguir de las nativas, pero imitar una aplicación nativa sigue siendo una tarea.y no dado como tal. Resumamos un poco. Escribir aplicaciones web, o más bien aplicaciones híbridas en iOS y Android, es posible y conveniente. Es conveniente porque el mecanismo de representación de la interfaz de usuario se encuentra completamente en la plataforma WebView, además hay una capa de programadores ya capacitados que están bien versados en la web.Sin embargo, en aplicaciones híbridas, el rendimiento y la integración del sistema operativo pueden ser poco convincentes.Al mismo tiempo que PhoneGap, MonoTouch se lanzó en 2009, que luego pasó a llamarse Xamarin.iOS. Además, en el mismo año, se lanzó Titanium, que a su vez también permitió escribir aplicaciones iOS en javascript. Al principio, Titanium trabajó exactamente en el mismo paradigma que PhoneGap: confiaba en WebView. Pero luego adoptaron el enfoque de Xamarin. ¿Cuál es este enfoque? Se puede ver como algo en el medio. El enfoque de Xamarin / Titanium / React.Native es que, en lugar de intentar crear / migrar su renderización de UI existente, el marco simplemente se integra con el nativo existente.En lugar de dibujar un formulario en HTML, Xamarin llama a un elemento UI nativo para esto (UITextField, TextEdit, etc.). De hecho, ¿por qué reinventar la rueda? Todos los elementos de IU necesarios existen en SDK nativos y tiempos de ejecución, solo necesita aprender a comunicarse con ellos desde sus máquinas virtuales (mono, v8, etc.). Al mismo tiempo, como ya lo adivinó, puede usar su C #, JS, TS, F #, Kotlin, etc. favoritos, y al mismo tiempo el código que no interactúa directamente con la interfaz de usuario es 100% multiplataforma. Puedes ir aún más lejos. El mismo UITextField y TextEdit son entidades conceptualmente idénticas, tienen bastantes propiedades e interfaces de interacción similares, y por lo tanto, puede crear una entrada abstracta (hola Xamarin.Forms) y trabajar solo con ella, por raro ( no muy)) excepción al elemento de la interfaz de usuario de la plataforma. No menciono que si su VM puede funcionar con la interfaz de usuario de forma nativa, lo más probable es que su VM pueda llamar a cualquier API de plataforma. Esta parece ser la opción perfecta. Interfaz de usuario nativa, rendimiento nativo (hola puentes en React.Native), integración 100% del sistema operativo. ¿Es esto realmente perfecto? Lo más probable es que no, y el problema es que en realidad estas soluciones no resuelven el problema del desarrollo multiplataforma: una sola interfaz de usuario. La disfrazan. Quiero escribir una vez, correr a todas partes. Esto está lejos de ser el mejor lema para todo tipo de programas y problemas, pero encaja bien con la interfaz de usuario. Quiero escribir la interfaz de usuario igual para todos, independientemente de la plataforma. ¿Por qué un desarrollador web puede permitirse usar HTML y CSS para escribir un sitio que luego se mostrará de la misma manera en Safari en iOS y Chrome en Android, pero no en un desarrollador nativo?De hecho, los programadores han escrito durante mucho tiempo una interfaz de usuario de alto rendimiento con una base de código común para iOS y Android. Estos programadores se llaman desarrolladores de juegos. Angry Birds fue escrito en el motor Cocos2d-x, Cuphead en Unity y Fortnite en Unreal Engine. Si los motores del juego pueden mostrar escenas impresionantes en su teléfono, entonces los botones y las listas con animación fluida definitivamente podrán hacerlo. Entonces, ¿por qué nadie los usa en esta línea? La respuesta es simple y banal, no están destinados a esto. Cuando abres el juego, depende absolutamente de la linterna cuánto se parece la IU a una nativa, casi nunca necesitas interactuar con geolocalización, botones, una cámara de video, etc. Mientras juegas, vives una vida diferente en tu pequeño mundo que se representa a través de Canvas en tu UIViewController / Activity. por lo tantolos motores de juego tienen una integración relativamente pobre con el sistema operativo , por lo que no hay (o no he visto) que imite el motor superior de la interfaz de usuario nativa.Subtotales
Para un marco multiplataforma ideal, necesitamos:- Mapeo de IU nativo
- Rendimiento nativo de la interfaz de usuario
- 100% de capacidad para llamar a cualquier API del sistema operativo, como si fuera una aplicación nativa
Ahora piensa que comenzaré a fallar bajo Flutter, pero ya escucho comentarios enojados: “¿Dónde está Qt? ¡Él puede hacer todo esto! De hecho, Qt en un grado u otro se ajusta a estos criterios. Aunque dudo mucho del primero de ellos. Pero el problema principal de Qt no es la dificultad de escribir una IU nativa, el problema principal es C ++. Entonces ya me estoy limpiando la cara del asador de codificadores de mano de obra en las ventajas. Pros es un cuchillo suizo con esteroides anabólicos, con los profesionales puedes hacer todo. Pero yo, como desarrollador frontend, no necesito todo esto. Necesito un lenguaje simple y comprensible que funcione con IU y E / S. Entonces, a nuestros tres puntos anteriores se agregó:- Lenguaje fácil de aprender y bastante expresivo.
- Rantime que encaja bien en el paradigma de desarrollo frontend
Bueno, ahora que hemos destacado algunas métricas de una buena herramienta multiplataforma para desarrollar aplicaciones móviles, podemos revisar cada una de ellas y ver cómo se implementa en Flutter.Mapeo de IU nativo
Como descubrimos anteriormente, hay dos enfoques opuestos para trabajar con UI en marcos multiplataforma. Este es un render de UI usando WebView o llamadas a elementos nativos de UI en cada plataforma. Cada enfoque tiene ventajas y desventajas. Pero no cubren la gama completa de necesidades del desarrollador: se ven indistinguibles del rendimiento nativo de UI + nativo. Flutter cubre todas estas necesidades con una cabeza. El equipo de Flutter gastó una cierta cantidad de recursos en la creación de elementos "nativos" en el propio marco. Todos los widgets en Flutter se dividen en tres grandes categorías:Si va a la sección de Cupertino, verá que estos widgets son indistinguibles de los elementos nativos de iOS. Como desarrollador que usa Flutter por un tiempo, puedo confirmar que no se pueden distinguir. Si usa CupertinoDatePicker, por ejemplo, al desplazarse sentirá exactamente lo mismo, una buena respuesta del motor Taptic / Haptic en su iPhone como si fuera un elemento nativo de la aplicación nativa. Diré más, periódicamente abro la aplicación del sitio realtor.com en mi iPhone y hasta hace poco no tenía idea de que estaba escrito en Flutter (o en algo no nativo).Flutter no solo te permite usar widgets "nativos" para 2 plataformas, sino también crear el tuyo propio, ¡y es muy fácil! Todo el paradigma es que todo funciona con widgets. Puede crear elementos de UI y animaciones increíblemente complejos en poco tiempo. Los encantos y la sabiduría del enfoque para trabajar con la interfaz de usuario en Flutter se han descrito recientemente en este artículo sobre Habr, recomiendo leer. Porque todo esto funciona en un único motor de gráficos que procesa directamente todo esto para cada plataforma (hablaremos de eso más adelante), puede estar seguro de que todo se mostrará como lo planeó.Otro punto bastante sorprendente. Flutter admite plataformas que comienzan con iOS 8 y Android API v16. Desde una perspectiva de representación de la interfaz de usuario, Flutter realmente no importa qué API están disponibles en una plataforma en particular. Tendría la oportunidad de trabajar con Canvas y algún tipo de interacción con el subsistema de gráficos. Y esto significa que podemos dibujar los últimos elementos de la interfaz de usuario de AndroidX, por ejemplo, en un teléfono de 8 años. Ciertamente hay una pregunta sobre el rendimiento de este enfoque en las plataformas compatibles más antiguas, pero esta es otra pregunta.Rendimiento nativo de la interfaz de usuario
Como puede ver, el enfoque de Flutter para la representación de la interfaz de usuario es más cercano al de las aplicaciones híbridas como Ionic. Tenemos un solo motor para renderizar la interfaz de usuario en todas las plataformas, esta es la Biblioteca de gráficos Skia . Google compró Skia como producto en 2005 y lo convirtió en un proyecto de código abierto. Esto al menos sugiere que este es un producto bastante maduro. Algunas características de rendimiento de Skia:- Copia en escritura para elementos gráficos y otros tipos de datos
- Usar memoria de pila siempre que sea posible para reducir la fragmentación
- Seguridad de roscas, para una mejor paralelización
No he encontrado pruebas de rendimiento convincentes de Skia en comparación con bibliotecas similares (ver El Cairo ), pero algunas pruebas muestran un aumento del rendimiento del 50% en promedio, excepto en algunas situaciones específicas. Sí, esto no es particularmente importante, porque estas pruebas se basan en el uso de OpenGL en equipos de escritorio y ...Skia puede interactuar con muchos backends de GPU. Desde recientetiempo en iOS, desde la versión 11, Flutter usa Metal como GPU de backend por defecto. En Android, comenzando con API 24 - Vulkan. Para las siguientes versiones: OpenGL. Todo esto nos da una ganancia obvia en productividad. En otras plataformas de "hardware", según tengo entendido, Skia / Flutter usa OpenGL, que en principio no nos impide escribir aplicaciones con suficiente rendimiento gráfico.La web se destaca. Por el momento, todo el procesamiento de la interfaz de usuario todavía se encuentra en el paquete Canvas / HTML. Por lo tanto, Skia no está involucrado de ninguna manera en este proceso. Además, la máquina virtual Dart no interactúa directamente con el DOM. Primero viene la conversión a js. Todo esto no tiene el mejor efecto sobre la productividad y es directamente perceptible a simple vista. Sin embargo, se está trabajando para implementar CanvasKiten Flutter, que a su vez permitirá que Skia se use en navegadores a través de WebGL.Finalmente, los programadores de C # han estado usando SkiaSharp durante un tiempo relativamente largo, un envoltorio sobre Skia para Mono / .Net x. Y la comunidad Xamarin usa esta biblioteca para dibujar elementos de IU personalizados y esta es una biblioteca muy popular. Si esto no es una victoria, entonces no sé qué es.100% de capacidad para llamar a cualquier API OS
En Flutter hay 2 principios de interacción con el mundo "exterior":Los canales de plataforma le permiten interactuar con el tiempo de ejecución / API nativo a través de un sistema de mensajería. Desde un punto de vista arquitectónico, esto se puede ver de la siguiente manera. Visualmente, Flutter es solo un Canvas, que se extiende a pantalla completa en el único Activity / UIViewController de su aplicación nativa. Este es exactamente el mismo enfoque que utilizo los desarrolladores de juegos (motores de juegos). Aquellos. Puede abrir el proyecto iOS / Android de su aplicación y agregar cualquier otra funcionalidad a Swift / Kotlin / etc. El problema es que el tiempo de ejecución nativo y Dart VM no sabrán nada el uno del otro (además del hecho de que el tiempo de ejecución nativo sabrá que la aplicación tiene Canvas y se muestra algo allí). Además, si, por ejemplo, abre el archivo MainActivity.kt de su proyecto de Android, verá algo como esto:class MainActivity: FlutterActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)
  }
}
¿Has notado que tu actividad hereda de FlutterActivity? Esto nos da la oportunidad de configurar el mecanismo para enviar mensajes directamente a Flutter / DartVM. Para hacer esto, necesitamos anular el método configureFlutterEnginey determinará el nombre del método llamado y el nombre del canal para enviar mensajes asincrónicos. Todas. ¡Esto hace posible escribirnos cualquier código nativo y llamar a cualquier API nativa! Al mismo tiempo, ya hay una gran cantidad de complementos (paquetes) que le evitan escribir código nativo, solo puede usar Dart. ¡Esto es simplemente maravilloso! Escribe la interfaz de usuario por separado y una vez para cualquier plataforma, usa DartVM para trabajar con la interfaz de usuario, E / S y solo como un componente informático, usa complementos que implementan características nativas y que cubren el 99% de toda la funcionalidad. Y si esto no es suficiente, usted escribe de forma nativa y se comunica a través del mecanismo del mensaje. Historia.El segundo mecanismo es una interfaz de función externa o FFI. Este es un término bastante común para el mecanismo de iterope con otros idiomas, principalmente C. En el mundo .Net, este mecanismo se llama P / Invoke, para JVM es JNI. En resumen, esta es la capacidad de interactuar con bibliotecas escritas en C / C ++ / etc. En el momento de .Net Framework, por ejemplo, no había software escrito en C # y la gran mayoría del software estaba escrito en C / C ++, por lo que se necesitaba un mecanismo para trabajar con estas bibliotecas. Lo mismo se aplica a JVM, Python, lo que sea. FFI se utiliza de una forma u otra en todos los marcos móviles multiplataforma. Más recientemente, DartVM también ha comenzado a admitir FFI para la interoperación con C y JavaScript. Si bien esta característica está en una rama beta, pero ya está disponible para su uso (bajo su propio riesgo y riesgo).Como puede ver, Flutter y DartVM cubren el 100% de las posibilidades en plataformas nativas, y aún más.Lenguaje fácil de aprender y bastante expresivo.
Lo admito honestamente, mientras que Dart para mí sigue sin ser el mejor idioma del mundo. No hay un sistema de tipo estricto, no hay bollos funcionales, como las características de coincidencia de patrones o inmutabilidad (como se entregarán pronto), etc. Sobre el sistema de tipos, Dart fue originalmente concebido como un lenguaje "sin un típico", ala JS, pero para el soporte normal para la compilación de AOT, sin embargo, fue necesario llevar el sistema de tipos a un nivel más estricto, aunque no completamente, diría yo. Todavía me molesta trabajar con firmas de métodos, es decir, con argumentos. Todos estos corchetes, @requiredpor alguna razón , son enfurecedores . Pero el dardo es un lenguaje muy fácil de aprender. En sintaxis, este es un cruce entre Java y JS para mí. Dart perdona mucho, como JS. En general, este es un lenguaje bastante fácil de aprender, no he experimentado ningún problema significativo.Rantime que encaja bien en el paradigma de desarrollo frontend
Ahora hablemos de Dart VM. En general, Dart VM incluye muchas cosas, desde GC hasta Profiler y Observatory. Aquí solo quiero hablar sobre GC y el tiempo de ejecución condicional. Puede familiarizarse con cómo funciona el tiempo de ejecución y en qué consiste aquí . No soy un experto en este campo, pero para mí, noté algunas de las ventajas de Dart VM, que trataré de describir. Antes de esto, me gustaría señalar que Dart y la máquina virtual correspondiente se desarrollaron inicialmente como un reemplazo para JS, que, por así decirlo, insinúa el enfoque en el desarrollo frontend.Aislamientos

Resumen
Si lees hasta esta línea, entonces, en primer lugar, felicidades, y en segundo lugar, tengo que decir que no tengo experiencia escribiendo artículos, por lo que no entiendo si logré comunicar mi punto de vista. Y la idea es simple, cuando escribes una aplicación móvil con Flutter, resulta nativa. Y en forma de bonificación, obtienes una velocidad de desarrollo de aplicaciones muy decente. Hot Reload / Restart es simplemente una cosa indispensable en el desarrollo de Frontend. ¿Te imaginas a alguien que necesite escribir / compilar todo el proyecto para cada navegador, por ejemplo, con cada cambio de color de un botón? Por supuesto no. En general, Hot Reload / Restart merece un artículo separado. Pero estaba distraído.Mi experiencia con Flutter me dice que este marco será dominante en el futuro cercano. Periódicamente, paso por entrevistas para un puesto de desarrollador de Flutter y, en la mitad de los casos, las empresas que buscan un desarrollador de Flutter en realidad tienen un equipo de desarrolladores nativos móviles. Simplemente probaron Flutter en proyectos interiores / secundarios, quedaron satisfechos / encantados y se mudaron lentamente a Flutter. Esta es una verdadera victoria, me parece. Lo que no se puede decir sobre Xamarin, desafortunadamente. Muy a menudo, la decisión de elegir Xamarin se debe simplemente al hecho de que el resto de la pila está escrito en .Net, que es una pendiente resbaladiza.Para resumir, quiero decir que si está pensando en qué lado abordar al desarrollar su nueva aplicación móvil, mire Flutter.