Skip to content

Backend

LathDevers edited this page May 4, 2023 · 11 revisions

Dart ist eine rein objektorientierte Sprache, da alle Objekte Instanzen von Klassen sind. Aber Dart erfordert nicht, dass der gesamte Code innerhalb einer Klasse definiert wird - es können Variablen, Konstanten und Funktionen auf oberster Ebene definieren, ähnlich wie in einer prozeduralen oder funktionalen Sprache.

Es gibt ein interessantes Paket namens fpdart, das funktionale Programmiereigenschaften in Dart ermöglicht.

Dart ist eine Garbage-Collected-Sprache mit einer C-ähnlichen Syntax.

In Flutter sind Backend und Frontend sehr eng ineinander integriert. Hier werden die beiden Layers nicht voneinander separiert entwickelt (z. B. Android XML Dateien).

Einführung in Dart

Datentypen und Datenstrukturen

Ein Guide zu lists, maps, sets und stacks.

Dart code is type-safe.

Klassen und mehr

Meistens wird eine Klasse in Flutter als eine Erweiterung (extends) der Klasse StatelessWidget oder StatefulWidget definiert und die verschiedenen Backendfunktionen schreibt man direkt in einem der Properties des Widgets (onPressed, onTap usw.). Natürlich kann man allerdings ohnehin Klassen definieren, die verschiedene Funktionen beinhalten und die dann in anderen Klassen instanziert werden können.

Class: Classes Tutorial
Mixin: What are mixins, Mixins in Dart
Hooks: flutter_hooks

Exploring Dart Constructors

Benannte und positionierte, optionale und erforderliche Parameter

Umschließe die benannten Parameter mit geschweiften Klammern { }.

class User {
  User(this.name, this._id, {this.age = 24, this.height, required this.nationality});
  String name; // positioned, not optional
  int? _id; // nullable, not optional, private
  int age; // named, optional, initialized
  double? height; // named, optional, not initialized but also nullable
  // actually, initial value is null
  String nationality; // named, required
}

User user1 = User('Jonas', 01234, nationality: 'German');
User user2 = User('Vivienne', null, age: 34, nationality: 'French');
User user3 = User('Robert', 98765, nationality: 'English', age: 12, height: null);

Umschließe die optionalen Parameter mit eckigen Klammern [ ].

class User {
  User(this.name, [this.age = 24, this.height]);
  String name; // positioned, not optional
  int age; // positioned, optional, non-nullable but initialized
  double? height; // positioned, optional, not initialized but nullable
}

List<User> users = [
  User('Jonas'),
  User('Vivienne', 34),
  User('Robert', 12, null),
  User('Sören', 52, 1.82),
];

Quelle

Code-Dokumentation und Möglichkeiten zum Kommentieren/Auskommentieren

Effective Dart: Documentation

Kommentare starten mit //. Alles nach dem // wird von Dart ignoriert.
Alternativ kann man auch ganze Codeabschnitte auskommentieren, indem man sie mit /* ... */ einschließen.

Zur Dokumentation von Klassen, Methoden oder Variablen: /// vor der Klassen-, Methoden- oder Variablendeklaration.

Beispiel:

/// Title text transfer fade.
const Duration _kNavBarTitleFadeDuration = Duration(milliseconds: 150);

/// An iOS-styled navigation bar with iOS-11-style large titles using slivers.
///
/// The [CupertinoSliverNavigationBar] must be placed in a sliver group such
/// as the [CustomScrollView].
///
/// ** See code in examples/api/lib/cupertino/nav_bar/cupertino_sliver_nav_bar.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [CupertinoNavigationBar], an iOS navigation bar for use on non-scrolling
///    pages.
///  * [CustomScrollView], a ScrollView that creates custom scroll effects using slivers.
class CupertinoSliverNavigationBar extends StatefulWidget { ...

Null selbst ist nicht das Problem, die Erfahrung zeigt, dass Entwickler dazu neigen, sehr oft Null-Fehler einzuführen. Null-Fehler verursachen Abstürze.

Null safety in Dart

Datentypen in Dart sind standardmäßig nicht-nullbar (non-nullable). Das bedeutet, dass man standardmäßig verpflichtet ist, einer Variablen beim Definieren einen Wert zuzuweisen, sie darf niemals null zugewiesen werden, es sei denn, man erlaubt es.

String s = "hello";

Schauen wir uns eine kompliziertere Situation an:

class User {
  User({required this.id, required this.name});

  int id;
  String name;
}

User user1;

print(user1.name);

In diesem Fall wird user1 kein Wert zugewiesen, so dass sein Wert null wäre (ohne null-safety). Beim Zugriff auf name wird die App abstürzen.

Um dies zu vermeiden, unterstreicht der Code Reviewer user1 und weist uns darauf hin, dass wir ihm einen Wert geben müssen.

Wenn man aus irgendeinem Grund eine neue Variable unbedingt mit keinem Wert definieren will, wir aber sicher sein können, dass die Variable beim ersten Lesen einen Wert hat, dann gibt es eine Abhilfe, indem wir die Variable mit dem Modifikator late definieren:

late User user1;

user1 = User( // variable gets value before reading it
  id: 0123,
  name: 'Moritz',
);

print(user1.name); // Moritz

Oder wir können auch die Variable nullable definieren, indem wir den null-aware Operator ? verwenden.

User? user1; // this means, that user1 is nullable

// so it can contain null
print(user1); // null
user1 = null;
print(user1); // null

// but before accessing its value, it has to get a value other than null
user1 = User(
  id: 0123,
  name: 'Moritz',
);

print(user1!.name); // Moritz

Nicht null ist schlecht, sondern die Tatsache, dass null dort auftaucht, wo man es nicht erwartet, verursacht Probleme.
Wir müssen diese Situation nur klug handhaben!
Entweder mit dem Operator !, wenn die Variable an der Stelle, an der man sie verwenden will, sicher nicht mehr null enthält:

String? s;
s = "hello"; // variable gets value before reading it
print(s!); // ! means: trust me, s has a value other than null

Oder durch die Implementierung verschiedener Aktionen, wenn der Wert der Variablen null ist oder nicht:

print(s ?? "hello"); // print s, but if s is null, then print "hello"

if (s != null) {
  action_if_s_is_not_null();
} else {
  action_if_s_is_null();
}

Je nach Situation gibt es also verschiedene Möglichkeiten, eine non-nullable Variable durch eine nullable zu ersetzen:

int? aNullableInt;
int aNonNullableInt = 5;

aNonNullableInt = aNullableInt!; // if you are sure, that aNullableInt is not null anymore at this point

aNonNullableInt = aNullableInt ?? 0;

aNullableInt != null ? aNonNullableInt = aNullableInt! : aNonNullableInt = 0; // ternary operator syntax

if (aNullableInt != null) aNonNullableInt = aNullableInt;

// the bug finder recognizes most of the time, that aNullableInt cannot be null because it was checked in the if statement.
// In some cases, especially if this logic is more complicated, the bug finder may not be so bright.
// Then just use the ! operator

// like here:

if (aNullableInt != null) aNonNullableInt = aNullableInt!;

// if using the ! operator is redundant, the bug finder warns you if the Flutter plugin is installed in either IntelliJ / Android Studio or VS Code
// for example
var someOtherVariable = aNonNullableInt!;
// or
if (aNonNullableInt != null)

Für weitere Informationen über Sound null-safety in Flutter kannst du entweder die Dart Seiten oder die Flutter Seiten lesen.

Asynchrone Programmierung

Isolates and Event Loops
Futures
Streams
Async/Await
Generators


<< Vorherige Seite | Nächste Seite >>

Clone this wiki locally