VoidCallback sendet ein Signal ohne Daten, während Function Callback einen Wert an das übergeordnete Widget zurückgibt. Dieser Leitfaden behandelt die Implementierung, technische Unterschiede und die Wahl des richtigen Callbacks für Flutter-Apps jeder Größe, einschließlich Spieleentwicklung und professioneller Benutzeroberflächen.
In der Flutter-Architektur ist die Kommunikation vom untergeordneten zum übergeordneten Widget eine klassische Herausforderung. Zwei leichte, eingebaute Lösungen sind VoidCallback und Function Callback. Beide ermöglichen es einem Kind, seinen Eltern zu benachrichtigen, ohne eine schwere Zustandsverwaltung wie Provider oder Bloc. Viele Anfänger wählen jedoch den falschen Typ, was zu ineffizientem oder schwer wartbarem Code führt. Dieser Artikel erklärt die grundlegenden Unterschiede, die korrekte Implementierung und ideale Anwendungsfälle – komplett mit sofort ausführbarem Code und Leistungsvergleichen.
Callbacks sind einfach Funktionen, die als Parameter übergeben werden. In Flutter entspricht VoidCallback
void Function(), während Function Callback je nach Bedarfvoid Function(int)odervoid Function(String, double)sein kann. Die richtige Wahl vereinfacht den Datenfluss und reduziert Fehler.
VoidCallback verstehen: Signal ohne Nutzlast
VoidCallback ist ein eingebauter Flutter-Typedef: typedef VoidCallback = void Function(). Er akzeptiert keine Argumente und gibt keinen Wert zurück. Verwenden Sie ihn, wenn ein untergeordnetes Widget sein übergeordnetes Widget nur darüber informieren muss, dass ein Ereignis aufgetreten ist – ohne zusätzliche Daten. Klassische Beispiele: ein „Gefällt mir“-Button, „Weiter“-Button oder ein Schalter, der einen booleschen Wert im Elternteil umschaltet.
Der Hauptvorteil von VoidCallback ist seine Einfachheit. Der Code bleibt lesbar und verschwendet keinen Speicher mit ungenutzten Daten. Die Einschränkung ist jedoch klar: Das übergeordnete Widget erhält keine zusätzlichen Informationen. Wenn Sie beispielsweise mehrere ähnliche Schaltflächen haben, kann das übergeordnete Widget nicht unterscheiden, welche gedrückt wurde, wenn Sie nur VoidCallback verwenden.
Function Callback: Daten an das übergeordnete Widget senden
Im Gegensatz zu VoidCallback ermöglicht ein Function Callback (oft als Callback mit Parametern bezeichnet) einem untergeordneten Widget, einen oder mehrere Werte an sein übergeordnetes Widget zurückzusenden. Es ist flexibel: Function(int), Function(String) oder sogar Function(double, bool). Die gesendeten Daten können Benutzereingaben, Spielerpositionen in einem Spiel oder Formularwerte sein.
Ein Beispiel aus der Praxis: Ein Lautstärkeregler innerhalb eines untergeordneten Widgets sendet einen Double-Wert von 0,0 bis 1,0 an das übergeordnete Widget, das dann den Tonpegel der App aktualisiert. Ohne Function Callback wüsste das übergeordnete Widget nie den genauen Wert, den der Benutzer ausgewählt hat. Daher erfordern interaktive Komponenten wie Slider, TextField oder DropdownButton praktisch einen Function Callback.
Wann VoidCallback verwenden? Wenn das übergeordnete Widget nur wissen muss, „dass“ etwas passiert ist, nicht „was“ oder „wie viel“. Beispiele: Navigationsbuttons, Aktualisierungsbuttons oder Animationsauslöser.
Wann Function Callback verwenden? Wenn das übergeordnete Widget spezifische Daten vom Kind benötigt, wie Zahlen, Text oder Objekte. Beispiele: Anmeldeformulare, Spielsteuerungen oder Suchfilter.
Ein Flutter-Projekt einrichten
Bevor Sie Callbacks implementieren, stellen Sie sicher, dass Ihre Flutter-Umgebung bereit ist. Erstellen Sie ein neues Projekt mit flutter create callback_demo oder verwenden Sie Android Studio. Installationsdetails finden Sie im offiziellen Flutter-Leitfaden. Öffnen Sie das Projekt, bereinigen Sie die Standarddatei lib/main.dart und bereiten Sie die folgende Dateistruktur vor.
Empfohlene Projektstruktur zur Trennung der Verantwortlichkeiten:
- main.dart – Einstiegspunkt, Thema und Routen.
- parent_widget.dart – Übergeordnetes Widget, das den Zustand und die Callback-Funktionen hält.
- voidcallback_child_widget.dart – Schaltfläche mit VoidCallback.
- function_child_widget.dart – Schaltfläche mit Function Callback (sendet einen Integer).
- slider_child_widget.dart – (optional) zusätzliches Beispiel mit Function Callback, das einen Double sendet.
Ändern Sie zuerst main.dart wie unten gezeigt.
import 'package:flutter/material.dart';
import 'parent_widget.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Callback Deep Dive',
theme: ThemeData(primarySwatch: Colors.indigo),
home: const ParentWidgetPage(title: 'VoidCallback vs Function Callback'),
);
}
}Das übergeordnete Widget mit Zustand erstellen
Das übergeordnete Widget hält einen Zähler und stellt zwei Funktionen bereit: _voidCallback (erhöht um 1) und _functionCallback(int i) (erhöht um den angegebenen Wert). Diese werden als Callback-Eigenschaften an untergeordnete Widgets übergeben. Zur besseren Übersicht fügen wir auch einen Reset-Button hinzu.
import 'package:flutter/material.dart';
import 'voidcallback_child_widget.dart';
import 'function_child_widget.dart';
class ParentWidgetPage extends StatefulWidget {
const ParentWidgetPage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<ParentWidgetPage> createState() => _ParentWidgetPageState();
}
class _ParentWidgetPageState extends State<ParentWidgetPage> {
int _counter = 0;
void _voidCallback() {
setState(() {
_counter++;
});
}
void _functionCallback(int i) {
setState(() {
_counter += i;
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Gesamtzahl der Klicks (oder akkumulierter Wert):',
style: TextStyle(fontSize: 16)),
Text('$_counter',
style: Theme.of(context).textTheme.headline4?.copyWith(
fontWeight: FontWeight.bold,
color: Colors.indigo,
)),
const SizedBox(height: 20),
ElevatedButton.icon(
onPressed: _resetCounter,
icon: const Icon(Icons.refresh),
label: const Text('Zähler zurücksetzen'),
style: ElevatedButton.styleFrom(backgroundColor: Colors.grey),
),
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
VoidChildWidgetPage(voidCallback: _voidCallback),
FunctionChildWidgetPage(functionCallback: _functionCallback),
],
),
),
);
}
}Im obigen Code aktualisiert setState die Benutzeroberfläche jedes Mal, wenn ein Callback ausgelöst wird. Die schwebenden Aktionsbuttons werden in einer Zeile mit zwei untergeordneten Widgets platziert, die jeweils den entsprechenden Callback erhalten. Der Reset-Button hilft bei der Demonstration, ohne die App neu starten zu müssen.
Ein untergeordnetes Widget mit VoidCallback erstellen
Das untergeordnete Widget für VoidCallback ist sehr einfach. Es akzeptiert eine Eigenschaft voidCallback vom Typ VoidCallback und ruft sie auf, wenn der Button gedrückt wird. Es werden keine Daten zurückgesendet. Um es informativer zu gestalten, fügen wir ein Symbol und eine QuickInfo hinzu.
import 'package:flutter/material.dart';
class VoidChildWidgetPage extends StatelessWidget {
final VoidCallback voidCallback;
const VoidChildWidgetPage({Key? key, required this.voidCallback})
: super(key: key);
@override
Widget build(BuildContext context) {
return Tooltip(
message: 'Erhöht den Zähler um 1, ohne Daten zu senden',
child: ElevatedButton.icon(
onPressed: () => voidCallback(),
icon: const Icon(Icons.notifications_none),
label: const Text("Void Callback"),
style: ElevatedButton.styleFrom(backgroundColor: Colors.teal),
),
);
}
}Dieser Button benachrichtigt nur das übergeordnete Widget, dass er angetippt wurde. Jeder Tipp ruft _voidCallback im Elternteil auf und erhöht den Zähler um 1. In Spielszenarien ist VoidCallback ideal für Aktionen wie „springen“ oder „Level neu starten“, die keine Parameter benötigen.
Ein untergeordnetes Widget mit Function Callback erstellen
Im Gegensatz zu VoidCallback ermöglicht Function Callback die Datenübertragung. Hier verwenden wir Function(int), damit das Kind jedes Mal die Ganzzahl 5 senden kann, wenn der Button gedrückt wird. Das übergeordnete Widget empfängt sie als Argument i in _functionCallback. Zur Abwechslung könnten Sie auch ein Kind erstellen, das dynamische Werte von einem Schieberegler sendet.
import 'package:flutter/material.dart';
class FunctionChildWidgetPage extends StatelessWidget {
final Function(int) functionCallback;
const FunctionChildWidgetPage({Key? key, required this.functionCallback})
: super(key: key);
@override
Widget build(BuildContext context) {
return Tooltip(
message: 'Erhöht den Zähler um 5, indem die Zahl 5 an das übergeordnete Widget gesendet wird',
child: ElevatedButton.icon(
onPressed: () => functionCallback(5),
icon: const Icon(Icons.data_usage),
label: const Text("Fx Callback (+5)"),
style: ElevatedButton.styleFrom(backgroundColor: Colors.deepPurple),
),
);
}
}Wenn Sie auf „Fx Callback (+5)“ klicken, ruft das Kind functionCallback(5) auf. Das übergeordnete Widget führt dann _functionCallback(5) aus und addiert 5 zum Zähler. Der gesendete Wert kann dynamisch sein (z. B. von einem Schieberegler oder Texteingabefeld), sodass das übergeordnete Widget immer aktuelle Daten erhält. Für die Spieleentwicklung ist Function Callback ideal zum Senden von Punktzahlen, Positionen oder Lebenspunkten an das übergeordnete Widget.

Führen Sie das Projekt mit flutter run oder der Play-Taste in Android Studio aus. Sie sehen zwei Hauptschaltflächen. Klicken Sie auf „Void Callback“, um den Zähler um 1 zu erhöhen, oder auf „Fx Callback (+5)“, um auf einmal 5 zu addieren. Dieses Verhalten beweist, dass Function Callback Werte zurückgeben kann, während VoidCallback dies nicht kann. Verwenden Sie die Reset-Taste, um von vorne zu beginnen.
Fallstudien: Spiele und Formulare
In einem einfachen mobilen Zahlenerraten-Spiel können untergeordnete Widgets Zahlenschaltflächen von 1 bis 9 sein. Jede Schaltfläche verwendet Function Callback mit ihrer Nummer als Parameter. Das übergeordnete Widget vergleicht dann die Zahl mit der richtigen Antwort. Ohne Function Callback wüsste das übergeordnete Widget nie, welche Nummer gedrückt wurde.
Ein weiteres Beispiel: ein Registrierungsformular. Jedes TextField kann einen Function Callback haben, der seinen Text bei jeder Änderung an das übergeordnete Widget sendet. Das übergeordnete Widget validiert und aktiviert die Senden-Schaltfläche nur, wenn alle Felder ausgefüllt sind. Dieses Muster ist sehr verbreitet und bildet die Grundlage des Lifting State Up (Zustandsanhebung).
Für Entwickler, die an ereignisbasierte Architekturen gewöhnt sind, ähneln Flutter-Callbacks den Event-Listenern in JavaScript. Sie sind jedoch typsicher, da die statische Typprüfung von Dart Inkonsistenzen frühzeitig erkennt.
Leistung und moderne Alternativen
Beide Callback-Ansätze sind leichtgewichtig und leicht verständlich, was sie perfekt für kleine Projekte oder UI-Komponenten macht, die keine komplexe Zustandsverwaltung benötigen. Aber in großen Anwendungen kann ein Übermaß an Callbacks zu einer Callback-Hölle (verschachtelter, schwer lesbarer Code) führen. Alternativen wie ValueNotifier, InheritedWidget oder das Provider-Paket bieten mehr Struktur.
Für die mobile Spieleentwicklung wird VoidCallback oft für Aktionen wie Springen oder Schießen verwendet, während Function Callback ideal ist, um Punktzahlen, Spielerpositionen oder Dauern an das übergeordnete Widget zu senden.
Leistungstechnisch haben Callbacks fast keinen Overhead, da sie direkte Funktionsaufrufe sind. Wenn jedoch Dutzende von Callbacks in einem einzigen Frame ausgelöst werden (z. B. während der Gestenverfolgung), sollten Sie die Verwendung von ValueNotifier mit AnimatedBuilder in Betracht ziehen, um nur die Teile neu aufzubauen, die sich ändern.
Fazit und praktische Empfehlungen
VoidCallback und Function Callback sind grundlegende, aber leistungsstarke Werkzeuge für die Widget-Kommunikation in Flutter. Verwenden Sie VoidCallback, wenn das Kind nur signalisieren muss, ohne Daten (wie Navigationsbuttons oder Animationsauslöser). Verwenden Sie Function Callback, wenn das Kind Werte zurücksenden muss (wie Formulardaten, Spieleereignisse oder Schiebereglerwerte). Beide sind einfach zu implementieren, benötigen keine zusätzlichen Abhängigkeiten und unterstützen das Muster des Lifting State Up perfekt.
Für größere Projekte sollten Sie eine Migration zu Provider oder Bloc in Betracht ziehen, aber Callbacks bleiben ein Muss für jeden Flutter-Entwickler. Wenn Sie diese Unterschiede verstehen, können Sie reaktionsfähigere, wartbare und fehlerfreie Oberflächen erstellen. Versuchen Sie, das Beispiel zu modifizieren: Erstellen Sie einen Function Callback, der einen Wert von einem Slider oder TextField sendet, und beobachten Sie, wie das übergeordnete Widget in Echtzeit reagiert. Viel Spaß beim Programmieren!
