Neue Anwendung "Jellyfish". Warum flattern?

Der technische Direktor Boris Goryachev spricht darüber, wie Medusa ein Jahr lang daran gearbeitet hat und warum es in Flutter geschrieben wurde


Am 12. Mai fand die Veröffentlichung der neuen mobilen Medusa-Anwendungen ( iOS , Android ) statt - fast zwei Jahre nachdem wir beschlossen hatten, sie neu zu schreiben. Warum so lange? Warum nicht native Apps? Warum flattern? All dies erzählt der technische Direktor der Medusa Boris Goryachev.



Im Gegensatz zu unseren alten Anwendungen haben wir beschlossen, keine neuen Anwendungen nativ zu machen. Erstens ist es mühsam, denselben Code zweimal zu schreiben. Zweitens wird es nie funktionieren, so dass in zwei verschiedenen Projekten, die von verschiedenen Leuten geschrieben wurden, alles synchron und gleich ist. Normalerweise arbeitet jemand langsamer, jemand macht Urlaub, jemand hat eine technische Schuld, die geschlossen werden muss. All unsere Erfahrung beim Erstellen und Unterstützen nativer Anwendungen hat uns dazu veranlasst - entweder machen wir etwas falsch oder dies ist einfach nicht unser Weg. Und wir begannen nach unseren zu suchen. Wir haben React Native und Ionic ausprobiert, über den Basecamp-Ansatz nachgedacht - alles im Web + eine dünne native Ebene - und sogar versucht, auf die Progressive Web App zuzugreifen und online zu bleiben.

Etwa zur gleichen Zeit nahm ich an einer Google I / O-Konferenz teil und traf dort Leute, die Flutter machen. Ich habe sofort Dart ausprobiert und ein bisschen an Flutter gearbeitet, aber zu diesem Zeitpunkt war die Technologie noch nicht für Medusa bereit: Es war unmöglich, verschiedene interaktive Materialien und Einbettungen in unsere Materialien einzubetten, aber dies ist für die Medien von entscheidender Bedeutung. Also beschloss ich zu warten, bis Flutter erwachsen wurde.

Während des Wartens haben wir viele Dinge auf der Webseite getan: Die Site neu geschrieben, eine neue Version von AMP geschrieben. Wir haben alle Projekte von Medusa geschrieben und auf ui-kit übertragen - eine einzige Bibliothek von Komponenten, die auf der Website verwendet werden und dank derer eine große Anzahl unserer Spielmechaniken möglich ist. Wir haben Desktop- und Mobilversionen der Site aufgeteilt, sodass die Verteilungsseiten (Haupt- und Abschnittsseiten) nach ihren eigenen Regeln an zwei verschiedenen Stellen erstellt wurden.

Parallel zur Arbeit auf der Website haben wir über eine neue Anwendung nachgedacht - wir haben die Navigation, Bedeutungen, Bildschirme, Funktionen usw. entwickelt.



Parallel dazu fanden wichtige Änderungen in der Struktur der technischen Abteilung statt. Wir haben begonnen, den Google-Kalender und andere Tools zur Besprechungsplanung aktiv zu nutzen, und sind von Trello zu Basecamp gewechselt. Es ist so offensichtlich, dass es sogar seltsam ist, darüber zu sprechen. Aber es hat viel Zeit und Mühe gekostet, das Chaos zu rationalisieren. Eine klare Agenda mit Besprechungen, eine schnelle Nachverfolgung, Dateien, die nicht verloren gehen, und Bereiche mit Bergkarten ermöglichten es, einen riesigen Strom von Aufgaben zu bewältigen und nicht zu sterben.

Warum flattert es immer noch? Und ein bisschen über Dart


Wenn Menschen etwas über Flutter lernen, lernen sie unweigerlich etwas über Dart. Es scheint, dass es als der größte Nachteil von Flutter angesehen wird, aber genau bis Sie versuchen, darauf zu schreiben. Er ist wirklich cool. Das Folgen von JavaScript ist etwas Besonderes.

Dart ist eine Programmiersprache, die von Google entwickelt wurde. Es wurde 2011 angekündigt, das heißt, es ist noch eine junge Sprache. Es ist (zumindest vorerst) keine wichtige Programmiersprache geworden, wird aber gleichzeitig im Unternehmen selbst sehr aktiv eingesetzt. Neben Google gibt es noch andere große Unternehmen, zum Beispiel Wrike, die Dart verwenden und einen vollständigen Stapel darauf schreiben.

Da sowohl Dart als auch Flutter von derselben Firma unterstützt werden, ist es möglich, die Sprache an die Bedürfnisse von Flutter anzupassen. Soweit ich weiß, interagieren beide Teams aktiv miteinander, sodass ständig Chips in der Sprache angezeigt werden, sodass Sie angenehmeren Code auf Flutter schreiben können.

Ich werde nicht versuchen zu erklären, woraus Flutter besteht - Wikipedia wird diese Aufgabe besser bewältigen, aber ich werde nur sagen, dass es unter den Autoren Leute gibt, die in Chrom gerendert haben.

Im Dezember 2018 veröffentlichte das Flutter-Team die Webview-Einbettungsbibliothek in Flutter. Es war roh und hat übrigens den Entwicklervorschau-Status immer noch nicht verlassen, aber diese Tatsache hat nicht aufgehört, die Struktur der zukünftigen Anwendung abzuschätzen. Ich habe mehrere Monate in meiner Freizeit experimentiert und dann eine endgültige Entscheidung getroffen.

Zuerst habe ich mich hingesetzt, um eine neue Version der API speziell für die Anwendung zu schreiben. Die Ideologie dieser API kann wie folgt formuliert werden: Wenn im Backend etwas getan werden kann, müssen Sie dies im Backend tun. Und nicht, weil es schwierig ist, etwas für den Kunden zu tun. Tatsache ist, dass Veröffentlichungen im App Store und bei Google Play ein mühsamer und langwieriger Prozess sind. Sie müssen sich an ihre Arbeitspläne anpassen und bedenken, dass nicht alle Benutzer die Anwendung sofort aktualisieren. Dies kann vermieden werden, wenn die Hauptlogik auf Ihrem Server ausgeführt wird. Müssen Sie den Titel um 10 Pixel nach unten verschieben? Bitte schön. Eine Komponente schnell entfernen oder hinzufügen? Kein Problem!



Aus dem gleichen Grund enthält die API für eine mobile Anwendung die einfachsten möglichen Komponenten, aus denen nahezu jedes Material rekursiv erfasst wird. Ich sage "fast", weil wir Spiele über WebView zeigen. Die Anwendung spielt keine Rolle, was angezeigt werden soll - eine Karte, ein Podcast, Nachrichten oder "Big Top". Alles wird von einem Code verarbeitet, und die Aufgabe der Anwendung besteht darin, die Komponente zu übernehmen und zu rendern (oder zur Liste ihrer untergeordneten Komponenten zu gehen und sie rekursiv aufzurufen).

Ein weiteres wichtiges Argument für Flutter: Der Entwickler "kontrolliert alle Pixel". Wenn Sie sicherstellen müssen, dass überall korrekte Schatten vorhanden sind, wie im Layout in Sketch, oder wenn Sie möchten, dass sich die Transparenz entlang der Kurven ändert, oder wenn Sie möchten, dass die Schriftgrößen und die gesamte Typografie anpassbar sind, ist alles in Flutter einfach und realistisch.

Ein weiteres Killer-Feature von Flutter ist der Entwicklungskomfort. Das Hot-Reload, an das ich in der Webentwicklung so gewöhnt bin, und die schnelle Geschwindigkeit beim erneuten Laden der Anwendung, ohne den Status zu verlieren, machen die Arbeit so einfach wie möglich. Sie müssen nicht warten, bis die Anwendung neu erstellt wurde, sondern warten, bis der neue Code funktioniert, und den Status wiederholen, in dem Sie arbeiten. Alles geht sehr schnell und cool.

Ökosystem


Obwohl Flutter und Dart noch keine sehr beliebten Technologien sind, hatten wir keine Probleme, Bibliotheken zu finden. Das meiste, was in der Anwendung benötigt wird, befindet sich entweder im Framework selbst oder auf pub.dev. Die Community ist sehr angenehm und bereit zu helfen. Diese Kommunikation ist ein echter Hauch frischer Luft, sehr unterstützend.

Darüber hinaus unterstützt Google selbst Flutter gut. Wir verwenden Firebase zum Pushen, Analysieren, Profilieren und Speichern von Benutzerdaten (Leseverlauf, Episodenpositionen, Lesezeichen), und alles funktioniert dort einfach. Natürlich ist es als Person, die noch nie native Anwendungen geschrieben hat, manchmal wild, in Gradle-Dateien zu klettern oder Eigenschaften in info.plist einzufügen. Aber normalerweise wird alles gegoogelt und es gibt nichts unglaublich Kompliziertes.

Plattformunterschiede


Sie können endlos über den Unterschied zwischen iOS und Android sprechen. In der Regel erinnern sie sich sofort daran, dass Muster dem Benutzer vertraut sein sollten und dass Designrichtlinien befolgt werden müssen. Wir sind damit einverstanden, aber nicht ganz. Es ist wichtig, sich an Ihre Corporate Identity, den gesunden Menschenverstand und die Verhaltenslogik der Ihnen bereits vertrauten Benutzer zu erinnern.

Wenn Sie sich den Verlauf der Plattformen selbst ansehen, sehen Sie, dass sich einige Muster mit den Geräten ändern, während andere vom System zum System fließen. Dies sind keine Tabletten, nichts steht still. Es gibt Dutzende cooler Beispiele, bei denen Unternehmen von den Empfehlungen von Google und Apple abweichen und das tun, was sie für richtig halten.



Das einfachste und anschaulichste Beispiel ist das Zurückwischen in iOS. Der Bereich des Bildschirms, der das Wischen akzeptiert, ist standardmäßig sehr klein und beträgt etwa 20 Pixel. So funktioniert die Mail-Anwendung auf iPhones und ist sehr unpraktisch. Auf Twitter ist dieser Bereich leicht erweitert, während er auf Telegramm einfach riesig ist! Telegramm auf Android hat eine eigene Art der Navigation von der Chat-Liste zum Chat, es ist eine Kreuzung zwischen iOS und Android. Ja, die Richtlinien sind cool, aber auf dem iPhone XR ist es sehr unpraktisch, mit dem Finger zum oberen linken Rand des Geräts zu gelangen. Deshalb haben wir (natürlich unter Berufung auf Daten) entschieden, dass in der Anwendung "Medusa" die Schaltfläche "Zurück" unter iOS unten angezeigt wird. Aber auf Android wird es überhaupt nicht sein. Dazu gibt es Svaypas (sowohl unsere eigenen als auch die neuen Android-Svaypas) und eine Systemschaltfläche "Zurück".

Mein Kollege, Art Director der Medusa Nastya Yarovaya, sagt:

Ich habe kleine Hände und ein großes Telefon. Es scheint lächerlich, aber es hat zwei wichtige Entscheidungen im Entwicklungsprozess beeinflusst. Zunächst schlug ich vor, die Swipe-Zone deutlich zu erhöhen (auf 50% erhöht) - die erste Abweichung von den Richtlinien. Als wir dann an den Navigations- und Funktionstasten im Material arbeiteten, schlug ich vor, die Zurück-Taste in das allgemeine Menü unten einzufügen - dies ist eine weitere Abweichung vom üblichen Muster in der Benutzeroberfläche. Jetzt können Sie es mit Ihrem Daumen erreichen, da sie hauptsächlich von ihm gescrollt werden.


Wir wissen, dass wir definitiv fliegen werden, weil wir gegen eine Reihe von Empfehlungen von Apple und Google verstoßen haben. Wenn überhaupt, verwenden wir auch Telefone und wissen, dass viele Muster veraltet sind, da sie zur Hälfte für die Geräte erfunden wurden.

Eine kleine Übung: wie es in Flutter funktioniert


Nach React und anderen reaktiven Frameworks können Sie in wenigen Tagen einen Prototyp auf Flutter erstellen. Allgemeine Vorstellung von Flutter - alles ist ein Widget. Flutter bietet zwei (tatsächlich drei) Paradigmen: Sie können Material-Widgets verwenden, die dem Konzept des Materialdesigns folgen. Sie können Cupertino-Widgets verwenden - Widgets, die unter iOS aussehen und sich so verhalten. Und du kannst alles selbst schreiben.

Grob gesagt gibt es zwei Arten von Widgets, mit denen ein Entwickler interagiert: zustandslos und zustandsbehaftet.

Zustandslose Widgets sind Plus- oder Minus-Widgets, die keine Logik enthalten, die den Status des Widgets ändern soll.

Stateful Widgets haben eine setState-Funktion (Hallo, reagiere!). Sie ändern den Status und das Widget wird neu gezeichnet.

Aber natürlich wird eine große Anwendung auf einfachem setState nicht weit gehen, daher ist eine Zustandsverwaltungslösung erforderlich.

Es gibt verschiedene Lösungen für Flutter. Beispielsweise gibt es ein BloC-Muster, in dem Streams und Ereignisse aus Datenquellen verwendet werden. Sie enthalten Geschäftslogik, die die Entstehung neuer Ereignisse provoziert. Diese Ereignisse werden von Widgets gehört und Widgets reagieren auf Änderungen.

Diejenigen, die nach React kommen, möchten vielleicht Redux ausprobieren. Theoretisch sollte es kein Problem geben, wenn Sie in React mit diesem Ansatz geschrieben haben.

Ich habe beide Ansätze ausprobiert und mich für einen dritten entschieden. Die Jellyfish App verwendet Provider. Dies ist eine Bibliothek, die nicht von Google geschrieben wurde, aber es ist interessant, dass Google, nachdem es Provider zu Hause ausprobiert hatte, begann, seinen BloC aufzugeben und sogar beschloss, Provider als separate Bibliothek zu wiederholen. Aber am Ende gab er die Idee auf, den Code eines anderen zu wiederholen, und begann, das zu verwenden und zu pflegen, was als Open Source geboren wurde.

Das Provider-Gerät ist ziemlich einfach. Dies ist ein Widget, in dem sich ein Status befindet. Dieser Status wird durch Funktionen geändert, die intern notifyListeners () aufrufen. Die Widgets, die auf Änderungen reagieren müssen, befinden sich im Widget-Baum. Sie sind entweder direkte untergeordnete Elemente des Widget-Anbieters oder untergeordnete Elemente seiner untergeordneten Elemente. Wenn notifyListeners () aufgerufen wird, erhalten Kinder neue Werte über den Kontext, und die Neuerstellung erfolgt.

In der Regel werden Anbieter ganz oben in der Anwendung angekündigt, und Sie können viele Anbieter gleichzeitig verwenden - jeder ist für seine eigene Geschäftslogik verantwortlich.

Jetzt verwenden wir acht Anbieter, die an verschiedenen Stellen der Anwendung „zuhören“. So funktioniert beispielsweise der Lesezeichenanbieter, mit dem Leser ihre Lieblingsmaterialien speichern, offline und von derselben Stelle auf verschiedenen Geräten lesen können.

Die Reaktion wird der Instanz zu Änderungen am Dokument von Firebase hinzugefügt, das Schlüssel zu Materialien enthält, die von Lesern mit Lesezeichen versehen wurden. Für jede Änderung dieses Dokuments wird die zugehörige Variable im Anbieter aktualisiert und notifyListeners aufgerufen. Infolgedessen zeigen alle Widgets, die diesen Anbieter abhören, das richtige Symbol.

Durch Anbieter wurde auch das Anwendungsthema gewechselt. Die Anwendung verfügt über ThemeProvider, der zwei Instanzen von Themen enthält - und tatsächlich ist es nur eine Karte mit unserer Benennung der Farben und der Farben selbst.

Infolgedessen erhält das Widget die richtige Farbe wie folgt:

TextSpan(
	text: block['data']['first'],
	style: TextStyle(
		color: Provider.of<ThemeProvider>(context)
        .current
        .bodyFontColor,                            
  fontFamily: 'Proxima Nova',
));

Der Anbietercode wäre, wenn er vereinfacht wäre:

class ThemeProvider extends ChangeNotifier {
  CustomThemeData current;
  
  CustomThemeData blackTheme = CustomThemeData(
    name: 'black',
    bodyFontColor: Color.fromRGBO(184, 184, 184, 1),
    ...
  );
  
  CustomThemeData lightTheme = CustomThemeData(
    name: 'black',
    bodyFontColor: Color.fromRGBO(184, 184, 184, 1),
    ...
  );
  
  ThemeProvider(withTheme, withFontMultiplier, withAutoTheme) {
    theme = withTheme;
    autoTheme = withAutoTheme;
    current = withTheme == 'light' ? lightTheme : blackTheme;
  }
}

Wenn Sie die aktuelle Variable ändern, werden dementsprechend alle Widgets, die Farben aus dem Thema übernehmen, ausnahmslos korrekt angezeigt.

Was weiter


In den letzten Wochen haben wir die neue Anwendung aktiv an einer Gruppe von mehreren hundert Lesern von Medusa getestet. Wir werden Ihnen in einem separaten Artikel erklären, wie die Tests verlaufen sind, aber ich werde nur feststellen, dass Flutter alle meine Erwartungen erfüllt hat. Ja, er hat eine Möglichkeit, nicht alle funktionsreichen Bibliotheken zu entwickeln, aber angesichts der Geschwindigkeit, mit der sich alles bewegt, komme ich zumindest für mich zu dem Schluss, dass Flutter mit Medusa eine lange Zeit dauern wird.

All Articles