3 Punkte von GN⁺ 2024-08-12 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Für Entwickler, die GUI-Programme in Rust erstellen möchten, wird ein Ansatz vorgeschlagen, bei dem Rust-Zustand und -Logik beibehalten und eine Flutter-UI angebunden wird
  • Flutters ausgereiftes plattformübergreifendes SDK, das Widget-Ökosystem, pixelgenaue Kontrolle und Hot Reload machen UI-Iterationsarbeit schneller
  • Es ist kein 100 % reiner Rust-Ansatz, ähnelt aber bestehenden Kompromissen für Rust-UIs, bei denen die UI-Schicht getrennt wird, etwa HTML/CSS/Slint oder makrobasierte DSLs
  • flutter_rust_bridge wird zur Bridge zwischen Rust und Flutter, indem es beliebige Typen, &mut, async, Traits, Results, Closures, Lifetimes usw. automatisch konvertiert
  • Die Struktur lässt sich an Beispielen einer Counter-App und einer Todo-List-App nachvollziehen; der vollständige Code liegt im Beispielverzeichnis des flutter_rust_bridge-Repositorys

Eine Rust-GUI mit Flutter anbinden

  • Rust wurde laut StackOverflow und GitHub acht Jahre lang als „meistgewünschte Programmiersprache“ genannt, und die Nachfrage nach GUI-Programmen in Rust ist groß
  • Der vorgeschlagene Ansatz besteht darin, mit Flutter und flutter_rust_bridge eine GUI an ein Rust-Programm anzubinden
  • Zum direkten Ausprobieren können das GitHub-Repository oder der Demo-Ordner verwendet werden

Warum Flutter verwenden

  • Flutter wurde laut StackOverflow als „beliebtestes plattformübergreifendes Mobile-SDK“ genannt und wird von vielen Entwicklern und Marken eingesetzt
  • Dank des umfangreichen Widget-Ökosystems lassen sich gewünschte UI-Funktionen leicht umsetzen
    • Es gibt auch Pakete für Dinge wie Confetti-Animationen
    • Flutter bietet vielfältige Widgets und Funktionen sowie Flexibilität mit pixelgenauer Kontrolle
  • Hot Reload erhöht die Iterationsgeschwindigkeit in Entwicklungsphasen mit vielen UI-Anpassungen
    • Nach Codeänderungen ist die aktualisierte UI fast sofort sichtbar, ohne den Zustand zu verlieren
    • Die Wartezeit auf erneutes Kompilieren wird reduziert
  • Dieselbe Codebasis kann nicht nur auf Android und iOS, sondern auch auf Linux, MacOS, Windows und im Web ausgeführt werden

Der Kompromiss: kein reines Rust

  • Dieser Ansatz ist nicht 100 % reines Rust
    • Rust übernimmt Zustand und Logik, Flutter die UI
    • Das ähnelt anderen Rust-UI-Ansätzen, die andere Sprachen verwenden, etwa benutzerdefinierte DSLs aus Makros, HTML/CSS oder Slint
  • Diese Trennung entspricht der Separation of Concerns und wird auch in anderen Fällen verwendet
  • Flutter gilt als leicht zu erlernen, wenn man Rust versteht
  • An der Web-Plattform gibt es teilweise Kritik; sie scheint eher für „Apps“ wie Google Earth oder den Rive-Animationseditor geeignet zu sein als für statische Webseiten
  • Flutter bringt viel Boilerplate- und Scaffold-Code mit
    • In kleinen Projekten werden diese Dateien meist nicht geändert, sodass sie praktisch kaum ins Gewicht fallen
    • In großen Projekten bedeutet die Möglichkeit zur Änderung zugleich mehr Anpassbarkeit

Was flutter_rust_bridge verbindet

  • Ziel von flutter_rust_bridge ist es, Rust und Flutter so natürlich zu verbinden, als wären sie eine einzige Sprache
  • Mehrere Elemente werden automatisch konvertiert
    • beliebige Typen
    • &mut
    • async
    • Traits
    • Results
    • Closure/Callback
    • Lifetimes
  • „Rust-GUI mit Flutter“ ist nur ein möglicher Anwendungsfall
  • Weitere Beispiele sind die Nutzung beliebiger Rust-Bibliotheken aus Flutter heraus oder ein Ansatz, bei dem Code wie Algorithmen in Rust geschrieben wird und der Rest in Flutter

Beispiel: Counter-App

  • Das Beispiel ist eine von mehreren Möglichkeiten, Rust und Flutter zu integrieren
  • flutter_rust_bridge ist ein universelles Tool, das keine bestimmte Struktur erzwingt; daher sind auch Redux- oder Elm-artige Ansätze möglich
  • Auf der Rust-Seite wird der Zustand mit #[frb(ui_state)] definiert und Änderungsmethoden werden mit #[frb(ui_mutation)] markiert
    • RustState enthält count: i32
    • new() initialisiert count mit 100
    • increment() erhöht count um 1
  • #[frb(ui_state)] und #[frb(ui_mutation)] sind sehr leichtgewichtig; es gebe keine versteckte Magie, und der Code umfasse nur etwa zehn Zeilen
  • Die Flutter-UI wird deklarativ geschrieben
    • ein Text, der den aktuellen Zählerstand anzeigt
    • ein TextButton, der state.increment aufruft
    • beide Elemente werden in einer Spalte zusammengefasst und mit Padding versehen
  • Wenn die UI während der Ausführung geändert wird, sind die Änderungen per Hot Reload sofort sichtbar

Beispiel: Todo-List-App

  • Die Todo-List-App ist ein optionaler Abschnitt der Vollständigkeit halber und zeigt einen von mehreren Ansätzen, die flutter_rust_bridge unterstützen kann
  • Der Rust-Zustand enthält Todo-Einträge, Eingabetext, Filter und die nächste ID
    • items: Vec<Item>
    • input_text: String
    • filter: Filter
    • next_id: i32
  • Item enthält id, content und completed
  • Filter enthält All, Active und Completed
  • Zustandsänderungen werden unter #[frb(ui_mutation)] implementiert
    • add() fügt mit dem aktuellen Eingabetext einen Eintrag hinzu und leert die Eingabe
    • remove(id) entfernt den Eintrag mit dieser ID
    • toggle(id) kehrt den Erledigt-Status um
  • Die Business-Logik besteht aus filtered_items() und Filter::check()
    • All lässt alle Einträge durch
    • Active lässt nur nicht erledigte Einträge durch
    • Completed lässt nur erledigte Einträge durch
  • Die Flutter-UI ordnet Textfeld, Listenansicht und eine Row mit Filter-Buttons in einer Spalte an
    • SyncTextField verbindet Eingabeänderungen und Submit mit Änderungen am Rust-Zustand
    • Jeder Todo-Eintrag besteht aus Checkbox, Text und Lösch-Button

Code-Standort und Ausführung

  • Der vollständige Code befindet sich im Repository flutter_rust_bridge
    • frb_example/rust_ui_counter
    • frb_example/rust_ui_todo_list
  • Der Großteil besteht aus automatisch erzeugten Boilerplate-Dateien, die durch Flutter-Funktionalität entstehen
  • Die zentralen Dateien sind src/app.rs und ui/lib/main.dart
  • Die Demo wird ausgeführt, indem im Verzeichnis ui folgender Befehl gestartet wird
    • flutter_rust_bridge_codegen generate && flutter run

Noch keine Kommentare.

Noch keine Kommentare.