Flattern unter der Haube: Bindung

Dieser Artikel ist eine direkte Fortsetzung meines vorherigen Artikels .



Für eine vollständige Wahrnehmung empfehle ich Ihnen, zuerst den auf dem Link angegebenen Artikel zu lesen oder ihn in Ihrem Gedächtnis zu aktualisieren. Darin analysierte ich einen der wichtigen Aspekte des Flutter-Geräts - das Zusammenspiel von Bäumen und die Verteilung der Verantwortung zwischen ihnen. Es bleibt jedoch die Frage offen: Wie ist die Funktionsweise des gesamten im ersten Teil beschriebenen Mechanismus organisiert? Dies werden wir in diesem Artikel zu verstehen versuchen.







Allgemeine Bestimmungen



Wenn Sie die technische Übersicht über Flutter öffnen , sehen wir an einem der Punkte das folgende Diagramm. Es zeigt die bedingten Ebenen, in die die Autoren des Frameworks es selbst einteilen. 



Flattergerüstschema


In der Tat, wie sie es selbst nannten, sehen wir einen Puffkuchen. Größere und kleinere Schichten können unterschieden werden.



Die Framework-Ebene ist alles, mit dem wir zum Zeitpunkt des Schreibens der Anwendung arbeiten, sowie alle Dienstprogrammklassen, mit denen wir mit der von uns geschriebenen Engine-Ebene interagieren können. Alles, was mit diesem Level zu tun hat, ist in Dart geschrieben.



Engine-Ebene - Eine niedrigere Ebene als die Framework-Ebene enthält Klassen und Bibliotheken, mit denen die Framework-Ebene funktioniert. Einschließlich Dart, Skia usw. der virtuellen Maschine usw.



Plattformebene - Plattformspezifische  Mechanismen, die für eine bestimmte Startplattform spezifisch sind.



Schauen wir uns die Framework-Ebene genauer an. Im Diagramm ist es in Form von Schichten von höherer bis niedriger Ebene dargestellt. Ganz unten sehen wir eine SchichtStiftung . Wie der Name schon sagt, ist diese Ebene auf Framework-Ebene etwas Grundlegendes und Grundlegendes. Wir finden diese Bibliothek und dies ist, was in ihrer Beschreibung geschrieben steht:



Grundelemente des Core Flutter-Frameworks.

Die in dieser Bibliothek definierten Features sind die Dienstprogrammklassen und -funktionen der untersten Ebene, die von allen anderen Ebenen des Flutter-Frameworks verwendet werden.




Die in dieser Bibliothek definierten Funktionen sind die Dienstprogrammklassen und die Funktionen der untersten Ebene, die von allen anderen Ebenen des Flutter-Frameworks verwendet werden.



Diese Bibliothek enthält auch BindingBase - die Basisklasse für alle Bindungen.



Bindung



Lassen Sie uns zunächst verstehen, was Bindung ist und wie sie in Flutter verwendet wird. Der Name selbst sagt uns, dass dies eine Art Verbindung ist. Die Dokumentation, die der Flutter-Befehl BaseBinding hinterlässt, enthält Folgendes: Basisklasse



für Mixins, die Singleton-Dienste bereitstellen (auch als "Bindungen" bezeichnet). Um diese Klasse in einer "on" -Klausel eines Mixins zu verwenden, erben Sie davon und implementieren Sie [initInstances ()]. Das Mixin wird garantiert nur einmal in der Lebensdauer der App erstellt (genauer gesagt, es wird bestätigt, wenn es zweimal im aktivierten Modus erstellt wird).



Dies ist die Basisklasse für verschiedene Kommunikationsdienste, die als Mixins dargestellt werden. Jedes dieser Mixins wird initialisiert und garantiert die Eindeutigkeit seiner Instanz während der Laufzeit der Anwendung.



BaseBindingIst eine abstrakte Basisklasse, schauen wir uns dann konkrete Implementierungen von Bindungen an. Unter anderem werden wir sehen:



ServicesBinding ist verantwortlich für die Weiterleitung von Nachrichten von der aktuellen Plattform an den Nachrichtendatenhandler (BinaryMessenger);



PaintingBinding ist für die Kommunikation mit der Rendering-Bibliothek verantwortlich.



Die RenderBinding ist für die Kommunikation zwischen dem Renderbaum und der Flutter-Engine verantwortlich.



WidgetBinding ist für die Kommunikation zwischen dem Widget-Baum und der Flutter-Engine verantwortlich.



SchedulerBinding - der Scheduler der nächsten Aufgaben, z.



  • Aufrufe eingehender Rückrufe, die das System in Window.onBeginFrame initiiert - beispielsweise Ereignisse für Ticker und Animationscontroller;
  • Aufrufe von fortlaufenden Rückrufen, die das Window.onDrawFrame-System initiiert, z. B. Ereignisse, um das Anzeigesystem nach Abschluss der eingehenden Rückrufe zu aktualisieren;
  • Post-Frame-Rückrufe, die nach fortlaufenden Rückrufen aufgerufen werden, bevor sie von Window.onDrawFrame zurückkehren;
  • Nicht-Rendering-Aufgaben, die zwischen Frames ausgeführt werden müssen.


SemanticsBinding ist für die Verbindung der Semantikschicht und der Flutter-Engine verantwortlich.



GestureBinding ist für die Arbeit mit dem Gesten-Subsystem verantwortlich.



Wie der Name schon sagt, sind Bindungen eine Kommunikationsschicht zwischen der Flutter-Engine-Ebene und der Framework-Ebene selbst, von denen jede für eine bestimmte Arbeitsrichtung verantwortlich ist.



WidgetsFlutterBinding



Um besser zu verstehen, wie alles zusammenarbeitet, schauen wir uns den Ort an, der der Ausgangspunkt für jede Flutter-Anwendung ist - den Aufruf von runApp. Die Methode, die wir aufrufen, befindet sich in der Datei binding.dart , und dies ist kein Zufall. Die Beschreibung besagt, dass das übergebene Anwendungs-Widget erweitert und an den Bildschirm angehängt wird. Mal sehen, was es macht:



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


Hier treffen wir auf WidgetsFlutterBinding - eine konkrete Implementierung einer Anwendungsbindung, die auf einem Widget-Framework basiert. Im Kern ist es der Klebstoff, der das Flutter-Gerüst und den Motor verbindet. Die WidgetsFlutterBinding besteht aus vielen der zuvor beschriebenen Bindungen : GestureBinding , ServicesBinding , SchedulerBinding , PaintingBinding , SemanticsBinding , RendererBinding , WidgetsBinding . So haben wir eine Schicht, die unsere Anwendung in alle notwendigen Richtungen mit der Flutter-Engine verbinden kann.



Kehren wir zum Starten der Anwendung zurück. In WidgetsFlutterBindingDie Methoden ScheduleAttachRootWidget und ScheduleWarmUpFrame werden aufgerufen . Lassen Sie uns sehen, was in ihnen passiert.



ScheduleAttachRootWidget



Die scheduleAttachRootWidget Methode ist eine verzögerte Umsetzung von attachRootWidget. Diese Methode gehört zu WidgetsBinding . Die Beschreibung besagt, dass das übergebene Widget an renderViewElement angehängt wird - das Stammelement des Elementbaums. 



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


Aus dem Code können wir ersehen, dass diese Methode den RenderObjectToWidgetAdapter erstellt, der das Stamm-Widget des Widget-Baums ist und als Brücke verwendet wird, die die Bäume miteinander verbindet. Wenn wir uns die Implementierung ansehen, werden wir feststellen, dass es kein RenderObject für sich selbst erstellt, sondern einen Wert aus dem Containerfeld zurückgibt, und wir übergeben die renderView von der RendererBinding an dieses, wenn wir es erstellen. Diese renderView ist das Stammelement des Renderbaums.



RenderView get renderView => _pipelineOwner.rootNode;



Der PipelineOwner ist tatsächlich der Manager, der den Renderprozess verwaltet.



Zurück zur attachRootWidget- Methode... Die Methode attachToRenderTree wird für den erstellten Adapter aufgerufen, mit dem wir zum ersten Mal den Stamm des Elementbaums erstellen. Es ist zu beachten, dass der buildOwner an die attachToRenderTree-Methode übergeben wird . Diese Klasse ist ein Widget-Baum-Build-Manager, der den Status von Widgets überwacht, den Aktualisierungsbedarf überwacht und eine Reihe weiterer wichtiger Aufgaben im Zusammenhang mit der Aktualisierung des Status des Widget-Baums ausführt. So erhalten wir genau die drei Flatterbäume, von denen jeder über Bindungen gespeichert und verwaltet wird.



ScheduleWarmUpFrame



Die scheduleWarmUpFrame Methode gehört zur SchedulerBinding und verwendet wird , um einen Rahmen zu planen , so bald wie möglich zu laufen , ohne auf das „Vsync“ Systemsignal wartet. Da die Methode beim Start der Anwendung verwendet wird, dauert das Auslösen des ersten Frames, der wahrscheinlich recht teuer ist, etwas länger. Diese Methode blockiert den Versand von Ereignissen bis zum Abschluss des geplanten Frames.



Wie wir sehen können, beziehen sich beide beim Start gestarteten Mechanismen auf verschiedene Bindungen und interagieren mit diesen, die wiederum eng miteinander verbunden sind und eine Interaktion mit dem System ermöglichen. Fassen wir mit dem folgenden Diagramm zusammen.







Fazit



Bindungen sind ein wichtiger Mechanismus zum Organisieren einer Flutter-Anwendung. Er verbindet verschiedene Aspekte der Anwendung miteinander sowie mit der Engine.



Dank ihm können wir unsere Bewerbung auf der obersten Ebene des Frameworks schreiben, ohne uns Gedanken darüber machen zu müssen, wie wir die kohärente Arbeit von allem anderen organisieren. Ich hoffe, dieser Artikel hilft Ihnen, diesen Teil des Flutter-Geräts zu verstehen.



Vielen Dank für Ihre Aufmerksamkeit!



Verwendete Materialien:



Flattern

https://flutter.dev/



All Articles