Nach einer langen Pause werde ich weiter über das beliebte Flutter-Framework in einem Frage-Antwort-Format sprechen. Den ersten Artikel für Android-Entwickler finden Sie
hier . Heute wird es nützliches Material für Entwickler für iOS geben.
Wenn Sie wenig Zeit für ein unabhängiges und gründliches Studium der Dokumentation haben, aber verstehen möchten, was Flutter gut ist und wie es verwendet wird, werfen Sie einen Blick unter die Katze.
Flattern. Teil 1. Für Android-EntwicklerFlattern. Teil 2. Für iOS-EntwicklerFlattern. Teil 3. Für reaktive EntwicklerFlattern. Teil 4. Für WebentwicklerFlattern. Teil 5. Für Xamarin.Forms-Entwickler
Inhalt:
- Ansichten
- Navigation
- Threading & Asynchronität
- Projektstruktur und Ressourcen
- ViewController
- Layouts
- Gesten und Touch-Event-Handling
- Anwendungs-Styling
- Eingabeformular
- Flutter Plugins
- Datenbanken und lokaler Speicher
- Benachrichtigungen
Ansichten
Frage:
Was ist das
UIView-Analogon in Flutter?
Die Antwort lautet:
WidgetUnterschiede:
UIView ist eigentlich das, was auf dem Bildschirm angezeigt wird. SetNeedsDisplay () wird aufgerufen, um die Änderungen anzuzeigen.
Widget - eine Beschreibung dessen, was auf dem Bildschirm angezeigt wird. Denn Veränderung wird neu geschaffen.
Weitere Informationen:
Flutter enthält die
Cupertino Widgets- Bibliothek. Es enthält Widgets, die
Apple Design-Richtlinien implementieren.
Frage:
Wie aktualisiere ich die Anzeige von Widgets?
Die Antwort lautet:
Verwenden von
StatefulWidget und seines
Status . Flutter hat zwei Arten von Widgets:
StatelessWidget und
StatefulWidget . Sie funktionieren auf die gleiche Weise, der einzige Unterschied liegt im Rendering-Status.
Unterschiede:
StatelessWidget hat einen unveränderlichen Status. Geeignet zum Anzeigen von Text, Logo usw. Das heißt Sollte sich das Element auf dem Bildschirm während der gesamten Anzeigezeit nicht ändern, passt es zu Ihnen. Es kann auch als Container für Stateful Widgets verwendet werden.
StatefulWidget verfügt über den Status State, in dem Informationen zum aktuellen Status gespeichert werden. Wenn Sie ein Element auf dem Bildschirm ändern möchten, während Sie eine Aktion ausführen (eine Antwort kam vom Server, der Benutzer hat auf eine Schaltfläche geklickt usw.), ist dies Ihre Option.
Ein Beispiel:
1) StatelessWidget - Text
Text( 'I like Flutter!', style: TextStyle(fontWeight: FontWeight.bold), );
2) StatefulWidget - Wenn Sie auf die Schaltfläche (FloatingActionButton) klicken, ändert sich der Text im Text-Widget von
I Like Flutter zu
Flutter is Awesome! import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
Frage:
Wie erstelle ich einen Bildschirm mit Widgets? Wo ist das
Storyboard ?
Die Antwort lautet:
Flutter hat kein
Storyboard . Alles, was im Widget-Baum gesetzt wurde, direkt im Code.
Ein Beispiel:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: Center( child: CupertinoButton( onPressed: () { setState(() { _pressedCount += 1; }); }, child: Text('Hello'), padding: EdgeInsets.only(left: 10.0, right: 10.0), ), ), ); }
Alle Standard-Widgets in Flutter können im
Widget-Katalog angezeigt werden.
Frage:
Wie kann eine Komponente im Layout hinzugefügt oder entfernt werden, während die Anwendung ausgeführt wird?
Die Antwort lautet:
Durch eine Funktion, die je nach Zustand das gewünschte Widget zurückgibt.
Unterschiede:
Unter iOS können Sie addSubview () oder removeFromSuperview () ausführen. In Flutter ist das nicht möglich, weil Widgets bleiben unverändert. Nur ihr Zustand kann sich ändern.
Ein Beispiel:
Ändern Sie den Text in Button, indem Sie auf FloatingActionButton klicken.
class SampleApp extends StatelessWidget {
Frage:
Wie animiere ich Widgets?
Die Antwort lautet:
Verwenden der
AnimationController- Klasse, die der Nachfolger der abstrakten Klasse
Animation <T> ist . Er kann die Animation nicht nur starten, sondern auch anhalten, zurückspulen, anhalten und in die entgegengesetzte Richtung abspielen. Funktioniert mit
Ticker , der ein Neuzeichnen des Bildschirms meldet.
Unterschiede:
Unter iOS können Sie eine Ansicht mit animate (withDuration: animations :) animieren. In Flutter muss die Animation mit dem AnimationController in Code geschrieben werden.
Weitere Informationen:
Weitere Informationen finden Sie in den
Widgets für Animation und Bewegung , im
Lernprogramm für Animationen und in der
Übersicht über Animationen .
Ein Beispiel:
Überblendungsanimation des Flutter-Logos.
class SampleApp extends StatelessWidget {
Frage:
Wie benutzt man
CoreGraphics ?
Die Antwort lautet:
Flutter verwendet die Canvas-API für die
Skia- Low-Level-Engine anstelle von CoreGraphics. Android verwendet eine ähnliche Canvas-API.
Weitere Informationen:
Flutter verfügt über zwei Klassen zum Zeichnen auf Leinwand:
CustomPaint und
CustomPainter . Der zweite implementiert Ihren Rendering-Algorithmus.
Lesen Sie hier mehr:
StackOverflowEin Beispiel:
class SignaturePainter extends CustomPainter { SignaturePainter(this.points); final List<Offset> points; void paint(Canvas canvas, Size size) { var paint = Paint() ..color = Colors.black ..strokeCap = StrokeCap.round ..strokeWidth = 5.0; for (int i = 0; i < points.length - 1; i++) { if (points[i] != null && points[i + 1] != null) canvas.drawLine(points[i], points[i + 1], paint); } } bool shouldRepaint(SignaturePainter other) => other.points != points; } class Signature extends StatefulWidget { SignatureState createState() => SignatureState(); } class SignatureState extends State<Signature> { List<Offset> _points = <Offset>[]; Widget build(BuildContext context) { return GestureDetector( onPanUpdate: (DragUpdateDetails details) { setState(() { RenderBox referenceBox = context.findRenderObject(); Offset localPosition = referenceBox.globalToLocal(details.globalPosition); _points = List.from(_points)..add(localPosition); }); }, onPanEnd: (DragEndDetails details) => _points.add(null), child: CustomPaint(painter: SignaturePainter(_points), size: Size.infinite), ); } }
Frage:
Wie ändere ich die Transparenz von Widgets?
Die Antwort lautet:
Wickeln Sie das
Deckkraft- Widget ein.
Unterschiede:
Unter iOS haben alle Ansichten die Erweiterung .opacity oder .alpha. In Flutter ersetzt diese Option das Wrapper-Widget.
Frage:
Wie erstelle ich benutzerdefinierte Widgets?
Die Antwort lautet:
Verfassen Sie Widgets in einem (anstelle von Vererbung).
Unterschiede:
In iOS können Sie die Ansicht, an der wir interessiert sind, übernehmen und Ihre eigene Logik hinzufügen. In Flutter wird ein Widget immer von StatelessWidget oder StatefulWidget geerbt. Das heißt Sie müssen ein neues Widget erstellen und die benötigten Widgets als Parameter oder Felder verwenden.
Ein Beispiel:
class CustomButton extends StatelessWidget { final String label; CustomButton(this.label); @override Widget build(BuildContext context) { return RaisedButton(onPressed: () {}, child: Text(label)); } } @override Widget build(BuildContext context) { return Center( child: CustomButton("Hello"), ); }
Navigation
Frage:
Wie implementiere ich die Navigation zwischen Bildschirmen in Flutter?
Die Antwort lautet:
Zum Navigieren zwischen Bildschirmen werden die Klassen
Navigator und
Route verwendet.
Unterschiede:
Flutter kennt keine Konzepte wie UIViewController und UINavigationController. Es gibt Navigator (Navigator) und Routen (Routen). Der Navigator ähnelt im Prinzip dem UINavigationController. Sie können die angegebene Route mit
push () oder
pop () ansteuern. Route ist eine Art UIViewController, aber in Flutter ist es üblich, es mit einem Bildschirm oder einer Seite zu vergleichen.
Flutter hat zwei Navigationsmethoden:
- Beschreiben Sie eine Karte mit Routennamen
- Navigieren Sie direkt zur Route.
Ein Beispiel:
void main() { runApp(CupertinoApp( home: MyAppHome(),
Frage:
Wie navigiere ich zu einer Drittanbieteranwendung?
Die Antwort lautet:
Entweder über
MethodChannel mit der iOS-Ebene der Anwendung
interagieren oder das
URL-Launcher- Plugin verwenden.
Frage:
Wie mache ich Popback in iOS ViewController?
Die Antwort lautet:
Durch Aufrufen von SystemNavigator.pop ().
Weitere Informationen:
SystemNavigator.pop () aus dem Dart-Code ruft in iOS den folgenden Code auf:
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController; if ([viewController isKindOfClass:[UINavigationController class]]) { [((UINavigationController*)viewController) popViewControllerAnimated:NO]; }
Wenn dies nicht der
Fall ist , können Sie Ihre Implementierung über
MethodChannel durchführen .
Threading & Asynchronität
Frage:
Wie schreibe ich asynchronen Code in Flutter?
Die Antwort lautet:
Dart implementiert ein Single-Thread-Ausführungsmodell, das auf
Isolaten ausgeführt wird . Bei der asynchronen Ausführung wird async / await verwendet, mit dem Sie möglicherweise aus C # -, JavaScript- oder Kotlin-Coroutinen vertraut sind.
Ein Beispiel:
Erfüllung der Anfrage und Rückgabe des Ergebnisses zur Aktualisierung der Benutzeroberfläche:
loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; http.Response response = await http.get(dataURL); setState(() { widgets = json.decode(response.body); }); }
Wenn die Antwort auf die Anforderung
eingeht , müssen Sie die
setState () -Methode aufrufen, um den
Widgetbaum mit den neuen Daten neu zu zeichnen.
Ein Beispiel:
Laden und Aktualisieren von Daten in einer
ListView :
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { List widgets = []; @override void initState() { super.initState(); loadData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: ListView.builder( itemCount: widgets.length, itemBuilder: (BuildContext context, int position) { return getRow(position); })); } Widget getRow(int i) { return Padding( padding: EdgeInsets.all(10.0), child: Text("Row ${widgets[i]["title"]}") ); } loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; http.Response response = await http.get(dataURL); setState(() { widgets = json.decode(response.body); }); } }
Frage:
Wie wird Code in einem Hintergrundthread ausgeführt?
Die Antwort lautet:
Wie oben erwähnt - Verwenden von Async / Warten und Isolieren (Isolieren).
Unterschiede:
Unter iOS können Sie Operation mit einer möglichen Neudefinition von Methoden verwenden. In Flutter "out of the box" müssen Sie nur async / await verwenden, um den Rest kümmert sich Dart.
Ein Beispiel:
Hier ist die Methode dataLoader () isoliert. Unabhängig davon können Sie umfangreiche Vorgänge ausführen, z. B. das Parsen großer JSONs, die Verschlüsselung, die Bildverarbeitung usw.
loadData() async { ReceivePort receivePort = ReceivePort(); await Isolate.spawn(dataLoader, receivePort.sendPort);
Frage:
Wie mache ich Netzwerkanfragen in Flutter?
Die Antwort lautet:
Flutter hat ein eigenes
HTTP-Paket .
Ein Beispiel:
Um das HTTP-Paket zu verwenden, fügen Sie es als Abhängigkeit in pubspec.yaml hinzu:
dependencies: ... http: ^0.11.3+16
Um die Anfrage auszuführen, rufen Sie wait in der Async-Funktion http.get () auf:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; [...] loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; http.Response response = await http.get(dataURL); setState(() { widgets = json.decode(response.body); }); } }
Frage:
Wie zeige ich Fortschritte?
Die Antwort lautet:
Verwenden des
ProgressIndicator- Widgets.
Ein Beispiel:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { List widgets = []; @override void initState() { super.initState(); loadData(); } showLoadingDialog() { return widgets.length == 0; } getBody() { if (showLoadingDialog()) { return getProgressDialog(); } else { return getListView(); } } getProgressDialog() { return Center(child: CircularProgressIndicator()); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: getBody()); } ListView getListView() => ListView.builder( itemCount: widgets.length, itemBuilder: (BuildContext context, int position) { return getRow(position); }); Widget getRow(int i) { return Padding(padding: EdgeInsets.all(10.0), child: Text("Row ${widgets[i]["title"]}")); } loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; http.Response response = await http.get(dataURL); setState(() { widgets = json.decode(response.body); }); } }
Projektstruktur und Ressourcen
Frage:
Wo können Ressourcen mit unterschiedlichen Auflösungen gespeichert werden?
Die Antwort lautet:
In Vermögenswerten.
Unterschiede:
In iOS verfügen Grafikressourcen über Images.xcasset, die sich im Assets-Ordner befinden. Flattern hat nur Vermögenswerte. Der Ressourcenordner kann sich an einer beliebigen Stelle im Projekt befinden. Schreiben Sie den Pfad dazu in die Datei pubspec.yaml.
Weitere Informationen:
Die Größe der Grafikressourcen in iOS und Flutter ist identisch und folgt dem auf der Dichte basierenden Format.
Ressourcenposition:
images/my_icon.png // Base: 1.0x image images/2.0x/my_icon.png // 2.0x image images/3.0x/my_icon.png // 3.0x image
Pfad in der Datei pubspec.yaml:
assets: - images/my_icon.png
Verwenden von
AssetImage :
return AssetImage("images/a_dot_burr.jpeg");
Asset direkt nutzen:
@override Widget build(BuildContext context) { return Image.asset("images/my_image.png"); }
Frage:
Wo kann man Saiten aufbewahren? Wie kann man sie lokalisieren?
Die Antwort lautet:
In statischen Feldern lagern. Lokalisieren Sie mit
intl Paket .
Ein Beispiel:
class Strings { static String welcomeMessage = "Welcome To Flutter"; } Text(Strings.welcomeMessage)
Frage:
Was ist das Gegenstück zu CocoaPods? Wie füge ich Abhängigkeiten hinzu?
Die Antwort lautet:
pubspec.yaml.
Weitere Informationen:
Flutter delegiert den Build an native Android- und iOS-Builder. Eine Liste aller gängigen Bibliotheken für Flutter at
Pub anzeigen.
ViewController
Frage:
Was entspricht
ViewController in Flutter?
Die Antwort lautet:
Alles in Flutter sind Widgets. Die Rolle von ViewController für die Arbeit mit der Benutzeroberfläche übernehmen Widgets. Und die Rolle der Navigation, wie im Abschnitt über die Navigation erwähnt, ist Navigator und Route.
Frage:
Wie gehe ich mit Lebenszyklusereignissen um?
Die Antwort lautet:
Verwenden der
WidgetsBinding- und der
didChangeAppLifecycleState () -Methode.
Weitere Informationen:
Flutter verwendet FlutterAppDelegate im systemeigenen Code und die Flutter-Engine sorgt dafür, dass Statusänderungen so unauffällig wie möglich behandelt werden. Wenn Sie jedoch je nach Zustand noch etwas arbeiten müssen, ist der Lebenszyklus etwas anders:
- inaktiv - Die Anwendung ist inaktiv und empfängt keine Benutzereingaben. Dieser Zustand ist nur in iOS, in Android gibt es kein Analogon;
- angehalten - Die Anwendung ist derzeit für den Benutzer unsichtbar, reagiert nicht auf Benutzereingaben, arbeitet jedoch im Hintergrund.
- wieder aufgenommen - Die Anwendung ist sichtbar und reagiert auf Benutzereingaben.
- Aussetzen - Anwendung wird angehalten. Dieser Zustand ist nur in Android, in iOS gibt es kein Analog.
Dies wird ausführlicher in der
AppLifecycleStatus-Dokumentation beschrieben .
Ein Beispiel:
import 'package:flutter/widgets.dart'; class LifecycleWatcher extends StatefulWidget { @override _LifecycleWatcherState createState() => _LifecycleWatcherState(); } class _LifecycleWatcherState extends State<LifecycleWatcher> with WidgetsBindingObserver { AppLifecycleState _lastLifecycleState; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { setState(() { _lastLifecycleState = state; }); } @override Widget build(BuildContext context) { if (_lastLifecycleState == null) return Text('This widget has not observed any lifecycle changes.', textDirection: TextDirection.ltr); return Text('The most recent lifecycle state this widget observed was: $_lastLifecycleState.', textDirection: TextDirection.ltr); } } void main() { runApp(Center(child: LifecycleWatcher())); }
Layouts
Frage:
Was ist das Äquivalent von
UITableView und
UICollectionView ?
Die Antwort lautet:
ListViewEin Beispiel:
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
Frage:
Woher weiß ich, auf welchen Listeneintrag geklickt wurde?
Die Antwort lautet:
Das Widget, das ein Element der Liste ist, muss den Klick darauf verarbeiten.
Unterschiede:
In iOS ist dafür die separate Methode tableView: didSelectRowAtIndexPath: verantwortlich. In Flutter muss das Listenelement in ein Widget eingeschlossen werden, das Klicks verarbeitet, z. B. den
GestureDetector .
Frage:
Wie aktualisiere
ich eine
ListView dynamisch?
Die Antwort lautet:
Aktualisieren Sie die Datenliste und rufen Sie setState () auf.
Unterschiede:
Unter iOS müssen Sie die Daten aktualisieren und die reloadData-Methode aufrufen. In Flutter wird das Widget nach setState () erneut gezeichnet.
Ein Beispiel:
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
Weitere Informationen:
Zum Erstellen einer Liste wird die Verwendung von
ListView.Builder empfohlen.
Ein Beispiel:
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
Frage:
Was ist das Analogon von
UIScrollView ?
Die Antwort lautet:
ListView mit Widgets.
Ein Beispiel:
@override Widget build(BuildContext context) { return ListView( children: <Widget>[ Text('Row One'), Text('Row Two'), Text('Row Three'), Text('Row Four'), ], ); }
Weitere Informationen:
Weitere Details
hier .
Gesten und Touch-Event-Handling
Frage:
Wie man onClick Listener für Widget in Flutter hinzufügt?
Die Antwort lautet:
Wenn das Widget Klicks unterstützt, dann in onPressed (). Wenn nicht, dann in onTap ().
Ein Beispiel:
In onPressed ():
@override Widget build(BuildContext context) { return RaisedButton( onPressed: () { print("click"); }, child: Text("Button"), ); }
In onTap ():
class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: GestureDetector( child: FlutterLogo( size: 200.0, ), onTap: () { print("tap"); }, ), ), ); } }
Frage:
Wie gehe ich mit anderen Gesten auf Widgets um?
Die Antwort lautet:
Verwenden des
GestureDetector . Sie können die folgenden Aktionen ausführen:
Tippen Sie auf
Doppeltippen
Lang drücken
Vertikal ziehen
Horizontal ziehen
Ein Beispiel:
Verarbeitung auf DoubleTap:
AnimationController controller; CurvedAnimation curve; @override void initState() { controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this); curve = CurvedAnimation(parent: controller, curve: Curves.easeIn); } class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: GestureDetector( child: RotationTransition( turns: curve, child: FlutterLogo( size: 200.0, )), onDoubleTap: () { if (controller.isCompleted) { controller.reverse(); } else { controller.forward(); } }, ), ), ); } }
Anwendungs-Styling
Frage:
Wie verwende ich das Theme (Theme) in der Anwendung?
Die Antwort lautet:
Verwenden des MaterialApp-Widgets oder der WidgetApp als Stammverzeichnis in der Anwendung.
Ein Beispiel:
class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, textSelectionColor: Colors.red ), home: SampleAppPage(), ); } }
Frage:
Wie verwende ich benutzerdefinierte Schriftarten?
Die Antwort lautet:
Sie müssen nur die Schriftartdatei in den Ordner stellen (denken Sie an den Namen selbst) und den Pfad dazu in pubspec.yaml angeben.
Ein Beispiel:
fonts: - family: MyCustomFont fonts: - asset: fonts/MyCustomFont.ttf - style: italic
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: Center( child: Text( 'This is a custom font text', style: TextStyle(fontFamily: 'MyCustomFont'), ), ), ); }
Frage:
Wie werden Text-Widgets formatiert?
Die Antwort lautet:
Parameter verwenden:
- Farbe;
- Dekoration;
- decorationColor;
- decorationStyle;
- fontFamily;
- fontSize;
- fontStyle;
- fontWeight;
- hashCode;
- Höhe;
- erben;
- letterSpacing;
- textBaseline;
- Wortabstand.
Eingabeformular
Frage:
Wie erhalte ich ein Benutzereingabeergebnis?
Die Antwort lautet:
Verwenden von
TextEditingController .
Ein Beispiel:
class _MyFormState extends State<MyForm> {
Weitere Informationen finden Sie hier:
Abrufen des Werts eines Textfelds .
Frage:
Was ist das Analogon von Hinweis in
TextInput ?
Die Antwort lautet:
Der
Tooltip kann mit
InputDecoration angezeigt und als Konstruktorparameter an das Widget übergeben werden.
Ein Beispiel:
body: Center( child: TextField( decoration: InputDecoration(hintText: "This is a hint"), ), )
Frage:
Wie zeige ich Validierungsfehler an?
Die Antwort lautet:
—
InputDecoration .
Ein Beispiel:
class SampleApp extends StatelessWidget {
Flutter
Frage:
GPS?
Die Antwort lautet:
geolocator .
Frage:
?
Die Antwort lautet:
image_picker .
Frage:
Facebook?
Die Antwort lautet:
flutter_facebook_login .
Frage:
Firebase?
Die Antwort lautet:
Firebase
Flutter first party plugins :
Frage:
() ?
Die Antwort lautet:
Flutter EventBus . :
developing packages and plugins .
Frage:
UserDefault?
Die Antwort lautet:
Shared_Preferences plugin ( Shared Preferences Android ).
Ein Beispiel:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { runApp( MaterialApp( home: Scaffold( body: Center( child: RaisedButton( onPressed: _incrementCounter, child: Text('Increment Counter'), ), ), ), ), ); } _incrementCounter() async { SharedPreferences prefs = await SharedPreferences.getInstance(); int counter = (prefs.getInt('counter') ?? 0) + 1; print('Pressed $counter times.'); prefs.setInt('counter', counter); }
Frage:
Core Data ?
Die Antwort lautet:
SQFlite .
Benachrichtigungen
Frage:
push-?
Die Antwort lautet:
Firebase_Messaging .
Fazit
. , , . « » . «-» . , ? 2016 Kotlin, - 2017. , , . , .
2016 Flutter Dart. , 2018 . . ! , , , . ( Google Fuchsia , , , Flutter ). — ! , — . . Apple Store!