Pakete in Dart nutzen - flutter-tutorial-de/dart-programming GitHub Wiki
Ein Grundsatz der Programmierung lautet: Erfinde das Rad nicht nochmal!
Im Idealfall wird Programmcode für die Lösung eines Problems nur einmal auf der Welt geschrieben und gepflegt. Danach kann jeder diese Lösung benutzen, anstatt selbst eine Lösung zu erfinden.
Zu diesem Zweck gibt es in Dart sogenannte Pakete (englisch "packages").
Ein Paket ist eine Menge von Funktionen und/oder Klassen, die bestimmten Konventionen genügen, die hier jedoch nicht weiter erörtert werden.
import paketname_als_string ;
import 'dart:math'; void main(){ print('sin(0.3): ${sin(0.3)}'); }
- Einbinden des Paketes 'dart:math', das bei Dart automatisch mitgeliefert wird (deswegen "dart:").
- Im Paket sind auch die trigonometrischen Funktionen wie
sin()
definiert. Daher ist der Aufrufsin(0.3)
zulässig. - Ist die Anweisung
import 'dart:math'
nicht vorhanden, kommt die Fehlermeldung: "The function 'sin' isn't defined - line 3".
Der Grund ist, dass der Compiler dadurch wesentlich langsamer werden würde. Denn er müsste stets alle Initialisierungen für alle Pakete durchführen, auch wenn das Paket nicht gebraucht wird. Auch wäre die Liste der Namen viel größer, was wiederum die Suche langsamer machen würde. Und ein Programm zum Zählen von Wörtern braucht beispielsweise keine mathematischen Funktionen usw.
Es gibt eine Reihe von Paketen, die bei Dart immer vorhanden sind. Die wichtigsten sind:
- dart:async - Asynchrone Programmierung.
- dart:collection - Weitere Container, z. B. doppelt verlinkte Listen.
- dart:convert - Datenconvertierung, z. B. Bytes nach UTF-8.
- dart:core - Das einzige Paket, das immer vorhanden ist, auch ohne Import: Enthält z. B. die Klasse String.
- dart:math - Mathematische Funktionen, z. B. sin().
- dart:io - Dateien, Verzeichnisse, Sockets...
- dart:isolate - Parallelausführung ("Threads").
- dart:html - Funktionen für die HTML-Bearbeitung, z. B. DOM-Elementypen.
Zu diesen von Dart vorgegebenen Paketen kommen noch Pakete von anderen Quellen, z. B. https://pub.dev: Hier sind Tausende Pakete von verschiedenen Autoren gespeichert, die für sehr viele Aufgaben fertige Lösungen anbieten. Wir werden im Verlauf des Tutorials immer wieder darauf zurückgreifen.
Hinweis: Dieses Beispiel kann unter Dartpad ausgeführt werden.
// import 'package:intl/intl.dart'; void main() { final dDay = DateTime(1944, 6, 6); final now = DateTime.now(); print('Heute ist $now, der D-Day war am $dDay.'); var moonLanding = DateTime.parse("1969-07-20 20:18:04Z"); final diffDays = now.difference(moonLanding).inDays; final dayOfWeek = ',Mo,Di,Mi,Do,Fr,Sa,So'.split(',')[moonLanding.weekday]; print('Die Mondlandung war vor $diffDays Tagen, ein $dayOfWeek.'); final sevenDaysLater = now.add(Duration(days: 60)); print('In einer Woche ist es $sevenDaysLater'); final linuxTime = now.millisecondsSinceEpoch ~/ 1000; print(*Sekunden seit 1.1.1970: $linuxTime'); /* final formatter = DateFormat('yyyy.MM.dd HH:mm:ss'); final formatted = formatter.format(now); print('Heute im Iso-Format: $formatted'); */ }
- Erste Zeile siehe unten.
-
DateTime(1944, 6, 6)
liefert ein Objekt der KlasseDateTime
mit den Parametern Jahr, Monat und Tag. Optional sind Stunde, Minute, Sekunde sowie Milli- und Mikrosekunden. -
DateTime.now();
Es wird die statische Methodenow()
aufgerufen, die eine Instanz vonDateTime
abliefert mit den Angaben zum aktuellen Zeitpunkt. -
'Heute ist $now'
Die Wandlung vomDateTime
benutzt das amerikanische Format. -
DateTime.parse("1969-07-20 20:18:04Z")
So wandelt man einen String in einDateTime
-Objekt, mittels statischer Methode. -
now.difference(moonLanding)
liefert ein Objekt vom TypeDuration
,.inDays
liefert das Attribut mit der Anzahl der Tage. - Das Attribut
weekday
liefert den Wochentag eines Datums als Zahl zwischen 1 und 7, 1 für Montag usw. -
',Mo,Di,Mi,Do,Fr,Sa,So'.split(',')
spaltet den String in eine Liste mit 8 Elementen (erstes Element ist der Leerstring)- aus dieser Liste wird dann der String mit der Wochentagsnummer herausgepickt, der Name des Wochentags.
- Die Methode
add()
erwartet als Parameter ein Objekt des TypsDuration
und liefert die Addition dieser Dauer zu dem Zeitpunkt des aufrufendenDateTime
-Objekts. -
millisecondsSinceEpoch()
liefert die Anzahl der Millisekunden seit dem "Beginn der Epoche", das ist der 01.01.1970, des aufrufendenden Objektes.- Der Operator
~/
ist die Ganzzahldivision, es wird also die Anzahl der Sekunden nach Epochenbeginn berechnet, das wird als "Linux-Zeit" bezeichnet.
- Der Operator
Die erste und die letzten Zeilen sind auskommentiert, weil diese im dartpad.dev nicht ausführbar sind. In anderen Ausführungsumgebungen kann dieser Quellcode aber ausgeführt werden, wenn der Kommentar entfernt wird.
-
import "..."
sorgt für die Verfügbarkeit der KlasseDateFormat
. -
formatter = DateFormat('yyyy.MM.dd HH:mm:ss')
Der Konstruktor wird mit Platzhaltern angewiesen, wie das Format aussehen soll.yyyy
steht für die vierstellige Jahreszahl,MM
für zweistellige Monatsnummer,dd
für den zweistelligen Tag im Monat usw. - Die Klasse leistet aber noch viel mehr: Es gibt Konstruktoren, die eine Lokalisierung des Datumsformats beherrschen, das Ergebnis der Formatierung passt dann zum eingestellten Ort (Länderkennung):
DateFormat.yMd()
liefert das Jahr, Monat und Tag in ortsspezifischer Reihenfolge.
Ein Paket, das mit dart:
beginnt, steht automatisch mit der Installation von Dart zur Verfügung.
Ein Paket, das mit package:
beginnt muss extra in ein Projekt eingebunden werden. Das geschieht in der Datei pubspec.yaml
im Projekt-Hauptverzeichnis.
Wir wollen das im vorigen Kapitel benannte Paket package:intl/intl.dart
benutzen.
- Dazu benötigen wir die aktuelle Versionsnummer: Wir gehen in einem Browser auf die Seite pub.dev
- Dort geben wir in dem Suchfeld (mit Lupe) ein:
intl
. - Der erste Treffer ist das Paket
intl
. In der Beschreibung steht beispielsweise: v 0.16.1 / 0.17.0-nullsafety.2 • Updated: Jan 6, 2020 [Published by a pub.dev verified publisher] dart.dev
- Die Version ist hier also
0.16.1
- Dort geben wir in dem Suchfeld (mit Lupe) ein:
- In der Datei
pubspec.yaml
tragen wir nach dem Kommentar #Dependencies folgende Zeile ein:
intl: ^0.16.1
- Die Zeile muss mit zwei Leerzeichen beginnen, also kein Tabulatorzeichen!
- Als Versionsnummer sollte die Nummer aus der obigen Beschreibung stehen
-
^0.16.1
bedeutet: Die Version muss größer oder gleich der Version 0.16.1 sein, aber kleiner als die nächste Hauptversionsnummer, hier1.0.0
. - Weiter oben in der Datei steht eine Variante der Versionsangabe:
sdk: '>=2.10.0 <3.0.0'
. Hier muss die Version im angegebenen Bereich liegen, das ist nur eine besser dokumentierende Schreibweise von^2.10.0
Wenn ein referenziertes Paket noch nicht veröffentlicht ist, es aber lokal verfügbar ist, so wird es mit lokaler Pfadangabe in der *.yaml-Datei eingetragen. Es wird dabei das Verzeichnis mit der *.yaml-Datei des eingebundenen Pakets angegeben:
... dart_bones: path: ../dart_bones
Für Dart gilt die Konvention, dass eine Versionsnummer aus drei Nummern besteht, wobei die letzte "Nummer" noch mit Zusätzen ergänzt werden kann.
Beispiele: 1.0.0
4.7.12+7
- Wenn eine Änderung stattfindet, die nicht abwärtskompatibel ist ("breaking change"), muss die erste oder die zweite Nummer hochgezählt werden.
- Eine Neuerung erfordert das Hochzählen der dritten Nummer.
- Ändert sich die API nicht, wird die Änderung mit
+<zahl>
dokumentiert.
Ist in IdeaIC die Datei pubspec.yaml
geöffnet, befinden sich über dem Dateiinhalt verschiedene Links. Mit dem Link Pub get
wird das Werkzeug pub
aufgerufen, das mit dem Argument get
überprüft, ob alle Pakete aus der Datei
schon zur Verfügung stehen. Wenn nicht, wird das Paket aus dem Netz heruntergeladen und integriert.
Ein Paket soll eine Aufgabe lösen, nur diese, diese Aufgabe aber gut!
Das bedeutet auch, dass Pakete selber andere Pakete benutzen können. Man spricht dann davon, dass das Paket A von Paket B abhängt. Das Werkzeug pub
löst diese Abhängigkeiten auf, indem Pakete, die refererenziert werden, automatisch heruntergeladen werden, falls dies nicht schon vorher passiert ist. Dabei werden die Versionsnummern überprüft.
Probiere im Terminal (in Windows "Eingabeaufforderung") aus:
gdev dsuche pub deps
Es wird eine Liste von Paketen mit Versionsnummern ausgegeben, die in dem Projekt zur Verfügung stehen.