Sobre Flutter, en resumen: conceptos básicos

Sobre Flutter, en resumen: conceptos básicos


Después del informe de Yura Luchaninov , decidí probar Flutter por mí mismo. Estirar el cerebro, y así había algo para relajarse con los hombres en la cocina. Las cosas se han ido. Empecé a mirar, luego leer, luego escribir. Y todo parece funcionar, se lanzan aplicaciones y lo que explican es comprensible, todo es simple. Pero no sin un "pero", no todos lo explican. Y dado que la plataforma, el YP, los enfoques e incluso el área temática son nuevos para mí, este tipo de molestia, porque "no empiezas", y ni siquiera sabes qué buscar en Google: ¿Dardo / Flutter / Ventana / Pantalla / Ruta / Widget?


Por supuesto, no quería volver a leer toda la documentación de Dart, Flutter y sus widgets, porque no tenía mucho tiempo, y solo quería echar un vistazo más de cerca a Flutter. ¡Sería genial si hubiera una pequeña guía que describa todo lo que necesita, pero no más, para comprender y escribir aplicaciones no demasiado complicadas en Flutter!


Sobre la guia


La mayoría de los artículos sobre este tema están bien escritos y no son complicados. El problema es que la mayoría de ellos requieren conocimientos que se consideran fundamentos básicos, que, sin embargo, no se mencionan en otros artículos que describen los conceptos básicos. En esta serie de artículos, quiero rectificar esta situación. Comencemos desde cero y, sin dejar nada de lo anterior sin atención, lanzaremos una o varias aplicaciones. En el proceso, aprenderemos cómo usar todos los componentes principales , crear una interfaz única , trabajar con módulos nativos y, por supuesto, ensamblar su aplicación para ambas plataformas .


Escribiré desde la perspectiva de un desarrollador web. La mayoría de ustedes probablemente estén familiarizados con la pila web, y la analogía con la plataforma familiar es mejor que la analogía con la construcción de casas o lo que sea, Animal, Perro, Foo, Bar ...


Trataré de resumir brevemente para no retrasarme. Y para los más curiosos, dejaré enlaces útiles sobre los temas discutidos.


Sobre la plataforma


Flutter es una plataforma joven pero muy prometedora que ya ha atraído la atención de grandes empresas que lanzaron sus aplicaciones . Esta plataforma es interesante por su simplicidad comparable al desarrollo de aplicaciones web y la velocidad de trabajo a la par con las aplicaciones nativas. El alto rendimiento de la aplicación y la velocidad de desarrollo se logran mediante varias técnicas:


  • A diferencia de muchas de las plataformas móviles más conocidas de la actualidad, Flutter no utiliza JavaScript de ninguna forma. Como lenguaje de programación para Flutter, se eligió Dart, que se compila en código binario, logrando así una velocidad de operaciones comparable a Objective-C, Swift, Java o Kotlin.
  • Flutter no utiliza componentes nativos , de nuevo, en ninguna forma, por lo que no tiene que escribir ninguna capa para comunicarse con ellos. En cambio, como los motores de juego (y sabes que los juegos tienen una interfaz de usuario muy dinámica), dibuja toda la interfaz por sí sola. Botones, texto, elementos multimedia, fondo: todo esto se dibuja dentro del motor gráfico en Flutter. Después de lo anterior, vale la pena señalar que la aplicación "Hello World" en Flutter ocupa muy poco espacio: iOS ≈ 2.5Mb y Android ≈ 4Mb.
  • Flutter utiliza un enfoque declarativo inspirado en el marco web ReactJS basado en widgets (en el mundo de la web llamados componentes) para construir la interfaz de usuario. Para un aumento aún mayor en la velocidad de la interfaz, los widgets se vuelven a dibujar según sea necesario , solo cuando algo ha cambiado en ellos (de forma similar a cómo lo hace Virtual DOM en el mundo del front-end).
  • Además de esto, el marco tiene una recarga en caliente incorporada , que es tan familiar para la web, y aún no estaba disponible en las plataformas nativas.

Sobre los beneficios prácticos de estos factores, recomiendo leer el artículo del desarrollador de Android que reescribió su aplicación de Java a Dart y compartió sus impresiones. Aquí solo saco el número de archivos / líneas de código nombrados por él antes (escrito en Java) - 179/12176, y después (reescrito en Dart) - 31/1735. En la documentación puede encontrar una descripción detallada de las características técnicas de la plataforma . Y aquí hay otro enlace, si está interesado en ver otros ejemplos de aplicaciones de trabajo .


Sobre Dart


Dart es un lenguaje de programación en el que tenemos que escribir aplicaciones para Flutter. Es muy simple, y si tiene experiencia con Java o JavaScript, lo aprenderá rápidamente.


Traté de escribir un artículo de revisión sobre Dart, tratando de describir solo el mínimo necesario para aprender Flutter. Pero hay tantos matices en este lenguaje que, a pesar de varios intentos de escribir un artículo de este tipo, todavía no pude hacerlo completamente completo y al mismo tiempo corto. Por otro lado, los autores de A Tour of the Dart Language hicieron un excelente trabajo al respecto.


Sobre entrenamiento


Este tema, como Dart, está muy bien descrito en la guía oficial. Solo podría copiarlo aquí, pero no lo haré.


Sin esperar nada, vamos a la página de guía de instalación , seleccionamos la plataforma y seguimos los pasos para instalar la plataforma en nuestro sistema. En nuestro editor, conectaremos complementos. En la misma guía hay instrucciones para configurar VS Code e IntelliJ . También hay complementos para Dart y Flutter para su editor (generalmente necesita instalar dos). Lanzamos la aplicación y verificamos su rendimiento .


Sugerencia para usuarios de OSX. Lo siento por el espacio ocupado por los marcos pintados del teléfono en el emulador de iOS, así que los apagué y cambié al iPhone 8 (no es tan "largo"):


  • Hardware → Device → iOS # → iPhone 8
  • Window → Show Device Bezels

Puedes vivir sin botones, porque hay teclas de acceso rápido: Shift + Cmd + H - esto es casa, Cmd + Right - y esto es para dar vuelta el teléfono, el resto se puede encontrar en el menú Hardware . Pero le aconsejo que active el teclado en pantalla, porque es importante comprender si es posible trabajar con la aplicación cuando el teclado bloquea regularmente la mitad de la pantalla: Cmd + K (funciona cuando el foco está en algún campo de entrada).


iPhone 8 y iPhone X con marcos
iPhone 8 y iPhone X con marcos


iPhone 8 y iPhone X sin bordes
iPhone 8 y iPhone X sin bordes


Sobre la estructura


Entraremos en la carpeta con la aplicación generada y veremos qué tenemos allí. No con todo, sino con el correcto:


  • lib/ - De acuerdo con los principios de pub (administrador de paquetes de Dart), todo el código se encuentra en esta subcarpeta;
  • pubspec.yml : las dependencias de la aplicación están escritas aquí que debe instalar para ejecutarlas, al igual que package.json , pero hay un matiz, necesita instalarlas no a través de la utilidad Dart estándar mencionada anteriormente, sino a través del comando Flutter: flutter pub get <package_name> ;
  • test/ - ¿sabes qué hay allí? Puede ejecutarlos llamando a flutter test ;
  • ios/ & android/ - carpetas con configuraciones para cada plataforma, indica qué derechos son necesarios para ejecutar la aplicación (acceso a la ubicación, bluetooth), iconos y todo lo que es específico de la plataforma.

Descubrimos la estructura, ve a la carpeta lib/ donde main.dart está esperando el archivo main.dart . Este, como puedes adivinar, es el mismo archivo en el que debemos ejecutar nuestra aplicación. Y comienza como en C (e incluso toneladas de otros) llamando a la función main() .


Acerca de los widgets (Hola mundo aquí)


En Flutter, todo se basa en widgets : hay vistas, estilos con temas y estados en widgets. Hay dos tipos principales de widgets: con y sin estado, pero aún no se trata de eso. Hagámoslo fácil.


Eliminar todo de main.dart . Pegue el siguiente código cuidadosamente leyendo los comentarios:


 import 'package:flutter/widgets.dart'; //     //  Dart      main() main() => runApp( //   runApp  Flutter Text( //  ,   ,   <span> 'Hello, World!!!', //   —     textDirection: TextDirection.ltr, //       ), ); 

runApp(…) toma un solo argumento: un widget que será la raíz de todo el proyecto. Por cierto, Hot-reload no puede recuperarlo, por lo que deberá reiniciar la aplicación.
Text(…) : Flutter no solo puede mostrar una cadena en la pantalla. Para mostrar texto, debe especificar Text . textDirection . Y esto no es una alineación de texto como la alineación de text-align , cuando se compara con la web, es un análogo de direction . Parte de la API para internacionalizar una aplicación. Text no funcionará hasta que sepa la dirección, pero no tiene que especificarlo en todas partes; a continuación, analizaremos cómo ajustar la dirección del texto para toda la aplicación.


¿Ya lanzaste la aplicación? "¡Hola mundo!" fuera! Parece ser ... ¿Sí? Pero algo obviamente salió mal.


Captura de pantalla de la aplicación en ejecución


El texto está bloqueado por la información del sistema. Tenemos todo el espacio de pantalla a nuestra disposición, y sacamos el widget desde el principio, donde, entre otras cosas, se muestra la información del sistema. Intentemos mover nuestro texto a alguna parte.


 import 'package:flutter/widgets.dart'; main() => runApp( Center( // ,      child: Text( 'Hello, World!', textDirection: TextDirection.ltr, ), ), ); 

Center(…) es un widget que le permite colocar otro widget pasado en el argumento child en el centro horizontal y verticalmente. A menudo verá child y children en aplicaciones Flutter, ya que casi todos los widgets usan estos nombres para transmitir widgets que deben dibujarse dentro del widget llamado.


Las composiciones de widgets se utilizan en Flutter para representar la interfaz de usuario, cambiar el aspecto e incluso transferir datos. Por ejemplo, el widget de Directionality(…) establece la dirección del texto para todos los widgets secundarios:


 import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: Text('Hello, World!'), ), ), ); 

Veamos otro widget muy importante y al mismo tiempo transformemos el aspecto de nuestra aplicación:


 import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( //  ! <div>   Flutter' //   Container  color    color: Color(0xFF444444), child: Center( child: Text( 'Hello, World!', style: TextStyle( //     ,    color: Color(0xFFFD620A), //     fontSize: 32.0, //    ), ), ), ), ), ); 

Captura de pantalla de la aplicación HelloWorld


Color(…) - color. La documentación indica diferentes formas de configurarlo, pero lo principal es simplemente pasar el número al constructor de la clase. En el ejemplo anterior, le pasamos al constructor un número escrito en forma hexadecimal, que es muy similar a HEX, solo al principio agregamos dos caracteres más que indican el grado de transparencia del color, donde 0x00 es absolutamente transparente y 0xFF no es transparente en absoluto.


TextStyle(…) : un widget aún más interesante, con el que puede establecer el color, el tamaño, el grosor, el espaciado de línea, agregar subrayado y más.


Aplicación Flutter escrita, hecha! En los muelles, puede leer cómo ensamblarlo para Android e iOS , hay enlaces en el mismo lugar que le permiten saber cómo enviarlo a la Tienda deseada. Para quien esto no es suficiente, a continuación le lancé un par de líneas más sobre Flutter, tal vez más ...


Pro widgets sin estado


Cómo usar widgets: hemos descubierto, ahora veamos cómo crearlos. Ya se mencionó anteriormente que hay widgets que tienen un estado y que no lo tienen. Hasta ahora, solo hemos utilizado widgets sin estado. Esto no significa que no lo tengan en absoluto, porque los widgets son solo clases y sus propiedades se pueden cambiar. Justo después de representar el widget, cambiar su estado no llevará a actualizar este widget en la interfaz de usuario. Por ejemplo, si necesitamos cambiar el texto en la pantalla, necesitaremos generar otro widget de Text y especificar el nuevo contenido que queremos mostrar. Tales widgets se pueden llamar constantes, si sabes a lo que me refiero. Y son simples, así que comencemos con ellos.


Para crear un widget sin estado, necesita:


  1. Crea un hermoso nombre para la nueva clase;
  2. Heredar una clase de StatelessWidget ;
  3. Implemente un método build() que tome un BuildContext como argumento y devuelva algún tipo de Widget .

 import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: MyStatelessWidget() ), ), ); class MyStatelessWidget extends StatelessWidget { //  @override   ,    , //         //  ,       @override Widget build(BuildContext context) { // [context]    return Text('Hello!'); } } 

Ejemplo de widget con un argumento:


 // … class MyStatelessWidget extends StatelessWidget { //   Stateless      final,   const final String name; //   MyStatelessWidget(this.name); //   @override Widget build(BuildContext context) { // [context]     return Text('Hello, $name!'); } } 

Sobre Stateless, no hay nada más que agregar ...


Acerca de la recarga en caliente


Tenga en cuenta que al cambiar el contenido de nuestro widget, la aplicación se redibujará automáticamente. Después de eliminar el widget de la función main() , Hot-reload comenzó a ayudarnos.


También es importante comprender que, debido al módulo lanzado para el intercambio en caliente, la aplicación se ejecuta en un orden de magnitud más lento.


Sobre GestureDetector


GestureDetector widget en acción


En la siguiente sección, trataremos con StatefulWidget (con widgets que cambian cuando cambia su estado). Para que esto sea interesante, necesitamos cambiar de alguna manera este estado, ¿de acuerdo? Cambiaremos el estado del widget en respuesta a toques en la pantalla. Para hacer esto, usaremos el GestureDetector(…) , un widget que no dibuja nada, pero monitorea los toques en la pantalla del teléfono inteligente e informa sobre ello llamando a las funciones que se le transfieren.


Cree un botón en el centro de la pantalla, cuando haga clic, se mostrará un mensaje en la consola:


 import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( color: Color(0xFFFFFFFF), child: App(), ), ), ); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: GestureDetector( //     onTap: () { //    GestureDetector //    ,      print('You pressed me'); }, child: Container( //     decoration: BoxDecoration( //   shape: BoxShape.circle, //     color: Color(0xFF17A2B8), //      ), width: 80.0, height: 80.0, ), ), ); } } 

Haga clic en el botón azul y vea el mensaje en la consola. Hacemos clic una y otra vez y vemos el mensaje en la consola. Una vez más ... Está bien, deja de pegar.


Widgets con estado


StatefulWidget : simple, incluso más simple que StatelessWidget . Pero hay un matiz: no existen por sí mismos, para su trabajo necesitamos otra clase que almacene el estado de este widget. Al mismo tiempo, su parte visual (los widgets en los que consiste) también se convierte en su estado.


Para comenzar, mira la clase de widget:


 // … class Counter extends StatefulWidget { //      ,     , //   createState() @override State<Counter> createState() => _CounterState(); //        State, //   State<> } 

Arriba, creamos un widget "vacío" que implementó un método createState() muy simple. Esta separación de presentación y estado permite a Flutter optimizar en gran medida la aplicación.


El objeto de estado es completamente sencillo. Además, es casi idéntico al de StatelessWidget escrito por nosotros anteriormente. Su principal diferencia es la clase padre.


 // … class _CounterState extends State<Counter> { //    -    , //      . //   ,     int counter = 0; //     ,       //   ,      Stateless . @override Widget build(BuildContext context) { //          , //     —  : return Center( child: GestureDetector( onTap: () { //  ,   ,    //  counter. setState(() { // setState()   ,    //      ,    ++counter; }); }, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF17A2B8), ), width: 80.0, child: Center( child: Text( //    counter '$counter', //      style: TextStyle(fontSize: 30.0), ), ), ), ), ); } } 

Ejecutar aplicación de contador


Tenga en cuenta que el nombre de la clase comienza con un guión bajo. En Dart, todos los nombres que comienzan con guiones bajos identifican valores privados. Y el estado de los widgets en Flutter generalmente se deja en privado, aunque esto no es necesario.


¡Qué maravillosa aplicación hemos hecho! Este es un gran resultado. Pero antes de terminar esta parte del curso, veamos un par de widgets más interesantes. Solo que esta vez escribiremos más código, solo para hacerlo más interesante. La mayor parte de la aplicación debería serle familiar, y el resto ya debería haberlo aprendido a comprender:


 import 'package:flutter/widgets.dart'; main() => runApp(App()); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.ltr, child: Container( padding: EdgeInsets.symmetric( vertical: 60.0, horizontal: 20.0, ), color: Color(0xFFFFFFFF), child: Content(), ), ); } } class Content extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ Counter('Manchester United'), Counter('Juventus'), ], ); } } class Counter extends StatefulWidget { final String _name; Counter(this._name); @override State<Counter> createState() => _CounterState(); } class _CounterState extends State<Counter> { int count = 0; @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 10.0), padding: EdgeInsets.all(4.0), decoration: BoxDecoration( border: Border.all(color: Color(0xFFFD6A02)), borderRadius: BorderRadius.circular(4.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // widget —    State,    //      ,      _CounterLabel(widget._name), _CounterButton( count, onPressed: () { setState(() { ++count; }); }, ), ], ), ); } } class _CounterLabel extends StatelessWidget { static const textStyle = TextStyle( color: Color(0xFF000000), fontSize: 26.0, ); final String _label; _CounterLabel(this._label); @override Widget build(BuildContext context) { return Text( _label, style: _CounterLabel.textStyle, ); } } class _CounterButton extends StatelessWidget { final _count; final _onPressed; _CounterButton(this._count, {@required this._onPressed}); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { _onPressed(); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 6.0), decoration: BoxDecoration( color: Color(0xFFFD6A02), borderRadius: BorderRadius.circular(4.0), ), child: Center( child: Text( '$_count', style: TextStyle(fontSize: 20.0), ), ), ), ); } } 

Otra aplicación de contador en Flutter


Tenemos dos nuevos widgets: Column() y Row() . Intenta descubrir qué están haciendo. En el próximo artículo, los consideraremos con más detalle, así como veremos más de un widget que le permite componer otros widgets juntos y crear una aplicación agradable usando la biblioteca Flutter llamada Material.


Sobre la tarea


Si desea leer algo más en su tiempo libre, aquí hay una lista de enlaces interesantes:


Source: https://habr.com/ru/post/es430918/


All Articles