Aleteo bajo el capó: Encuadernación

Este artículo es una continuación directa de mi artículo anterior .



Para una percepción completa, le aconsejo que primero lea el artículo indicado en el enlace o lo actualice en su memoria. En él, analicé uno de los aspectos importantes del dispositivo Flutter: la interacción de los árboles y la distribución de responsabilidades entre ellos. Sin embargo, la pregunta permanece abierta: ¿cómo se organiza el funcionamiento de todo el mecanismo descrito en la primera parte? Esto es lo que intentaremos entender en este artículo.







Provisiones generales



Si abres el resumen técnico de Flutter , en uno de los puntos veremos el siguiente diagrama. Muestra los niveles condicionales en los que los autores del marco lo dividen ellos mismos. 



Esquema de marco Flutter


De hecho, como lo llamaron ellos mismos, vemos un pastel de hojaldre. Se pueden distinguir capas más grandes y más pequeñas.



El nivel de framework es todo aquello con lo que trabajamos al momento de escribir la aplicación, y todas las clases de utilidad que nos permiten interactuar con el nivel de motor que hemos escrito. Todo lo relacionado con este nivel está escrito en Dart.



Nivel de motor : un nivel inferior al nivel de marco, contiene clases y bibliotecas que permiten que el nivel de marco funcione. Incluyendo la máquina virtual Dart, Skia, etc.



Capa de plataforma:  mecanismos específicos de la plataforma específicos de la plataforma de lanzamiento.



Echemos un vistazo más de cerca al nivel del marco. En el diagrama, se muestra en forma de capas desde el nivel superior al nivel inferior. En la parte inferior vemos una capaFundación . Como sugiere el nombre, esta capa es algo fundamental y básico a nivel de framework. Encontramos esta librería y esto es lo que está escrito en su descripción:



Primitivas del framework Core Flutter.

Las características definidas en esta biblioteca son las clases de utilidad de nivel más bajo y las funciones utilizadas por todas las demás capas del marco Flutter.




Las funciones definidas en esta biblioteca son clases de utilidad y funciones de nivel más bajo utilizadas por todas las demás capas del marco Flutter.



Esta biblioteca también contiene BindingBase , la clase base para todos los enlaces .



Unión



Primero, entendamos qué es Binding y cómo lo usa Flutter. El nombre en sí nos dice que se trata de algún tipo de conexión. La documentación que deja el comando Flutter en BaseBinding nos dice lo siguiente:



Clase base para mixins que brindan servicios singleton (también conocidos como "bindings"). Para usar esta clase en una cláusula ʻon` de un mixin, herede de ella e implemente [initInstances ()]. Se garantiza que el mixin solo se construirá una vez en la vida útil de la aplicación (más precisamente, se afirmará si se construye dos veces en modo marcado).



Esta es la clase base para varios servicios de comunicación, que se presentan como mixins. Cada uno de estos mixin se inicializa y garantiza la singularidad de su instancia durante la vida de la aplicación.



BaseBindingEs una clase abstracta base, luego veamos implementaciones concretas de enlaces. Entre ellos veremos:



ServicesBinding se encarga de reenviar mensajes desde la plataforma actual al manejador de datos de mensajes (BinaryMessenger);



PaintingBinding es responsable de comunicarse con la biblioteca de renderizado.



RenderBinding es responsable de la comunicación entre el árbol de renderizado y el motor Flutter.



WidgetBinding es responsable de la comunicación entre el árbol de widgets y el motor Flutter.



SchedulerBinding es un programador para tareas regulares, como:



  • llamadas a devoluciones de llamada entrantes que el sistema inicia en Window.onBeginFrame, por ejemplo, eventos de controlador de animación y ticker;
  • llamadas a devoluciones de llamada continuas que el sistema Window.onDrawFrame inicia, por ejemplo, eventos para actualizar el sistema de visualización después de que se completan las devoluciones de llamada entrantes;
  • devoluciones de llamada posteriores al marco, que se llaman después de devoluciones de llamada continuas, antes de regresar de Window.onDrawFrame;
  • tareas de no renderización que se deben realizar entre fotogramas.


SemanticsBinding es responsable de vincular la capa semántica y el motor Flutter.



GestureBinding es responsable de trabajar con el subsistema de gestos.



Como sugiere el nombre, los enlaces son una capa de comunicación entre el nivel del motor Flutter y el nivel del marco en sí, cada uno de los cuales es responsable de una dirección específica del trabajo.



WidgetsFlutterBinding



Para comprender mejor cómo funciona todo en conjunto, veamos el lugar que es el punto de partida para cualquier aplicación de Flutter: la llamada a runApp. El método al que llamamos está en el archivo binding.dart y esto no es una coincidencia. La descripción dice que expande el widget de la aplicación pasada y lo adjunta a la pantalla. Veamos que hace:



void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}


Aquí es donde nos encontramos con WidgetsFlutterBinding , una implementación concreta de un enlace de aplicación basado en un marco de widgets. En esencia, es el pegamento que mantiene unidos la estructura y el motor de Flutter. WidgetsFlutterBinding consta de muchos de los enlaces que comentamos anteriormente: GestureBinding , ServicesBinding , SchedulerBinding , PaintingBinding , SemanticsBinding , RendererBinding , WidgetsBinding . Por lo tanto, obtuvimos una capa que puede conectar nuestra aplicación en todas las direcciones necesarias con el motor Flutter.



Volvamos a iniciar la aplicación. En WidgetsFlutterBindingse llaman los métodos scheduleAttachRootWidget y scheduleWarmUpFrame , veamos qué sucede en ellos.



ScheduleAttachRootWidget



El método scheduleAttachRootWidget es una implementación diferida de attachRootWidget. Este método pertenece a WidgetsBinding . La descripción dice que adjunta el widget pasado a renderViewElement, el elemento raíz del árbol de elementos. 



void attachRootWidget(Widget rootWidget) {
    _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
      container: renderView,
      debugShortDescription: '[root]',
      child: rootWidget,
    ).attachToRenderTree(buildOwner, renderViewElement);
}


A partir del código, podemos ver que este método crea el RenderObjectToWidgetAdapter, que es el widget raíz del árbol de widgets y se utiliza como un puente que conecta los árboles entre sí. Al observar su implementación, veremos que no crea un RenderObject por sí mismo, sino que devuelve un valor del campo contenedor, y le pasamos el renderView del RendererBinding cuando lo creamos. Este renderView es el elemento raíz del árbol de renderizado.



RenderView obtener renderView => _pipelineOwner.rootNode;



PipelineOwner es en realidad el administrador que administra el proceso de renderizado.



Volver al método attachRootWidget... Se llama al método attachToRenderTree en el adaptador creado, con el que creamos la raíz del árbol de elementos por primera vez. Cabe señalar que buildOwner se pasa al método attachToRenderTree . Esta clase es un administrador de construcción del árbol de widgets que monitorea el estado de los widgets, monitorea la necesidad de actualización y realiza una serie de otras tareas importantes relacionadas con la actualización del estado del árbol de widgets. Por lo tanto, obtenemos los tres árboles Flutter, cada uno de los cuales se almacena y administra a través de Bindings.



ScheduleWarmUpFrame



El método scheduleWarmUpFrame pertenece a SchedulerBinding y se utiliza para programar un marco para que se inicie lo antes posible sin esperar la señal del sistema "Vsync". Dado que el método se utiliza durante el inicio de la aplicación, el primer fotograma, que probablemente sea bastante caro, tardará más en activarse. Este método bloquea el envío de eventos hasta la finalización del marco programado.



Como podemos ver, ambos mecanismos lanzados al inicio se relacionan e interactúan con varios Bindings, que a su vez están estrechamente relacionados y brindan interacción con el sistema. Resumamos con el siguiente diagrama.







Conclusión



Los enlaces son un mecanismo importante para organizar una aplicación Flutter. Es él quien conecta varios aspectos de la aplicación entre sí, así como con el motor.



Incluso gracias a él, podemos escribir nuestra aplicación en la parte de más alto nivel del marco, sin preocuparnos por cómo organizamos el trabajo coherente de todo lo demás. Espero que este artículo te ayude a comprender esta parte del dispositivo Flutter.



¡Gracias por su atención!



Materiales usados:



Flutter

https://flutter.dev/



All Articles