Flutter Cheatsheet¶
Flutter - Erstellen Sie Apps für jeden Screen
__ Flutter ist das UI-Toolkit von Google, um schöne, native zusammengestellte Anwendungen für mobile, Web und Desktop von einer einzigen Codebasis zu erstellen. Es ist bekannt für seine expressive UI, schnelle Entwicklung Zyklus und native Leistung.
__
Inhaltsverzeichnis - (#Installation) - (#getting-started) - Core Concepts - (Widgets) (#widgets) - (Layouts) - (Navigation) - (#state-management) - (Networking) (#networking) - (Verlust) - (#animations) - (#platform-integration) - (Testen) - (#debugging) - (# Bereitstellung) - (#best-practices) - (Troubleshooting)
• Installation
Flutter SDK¶
# Download Flutter SDK from https://flutter.dev/docs/get-started/install
# Extract the zip file
# Add Flutter to your path (for the current terminal session)
export PATH="$PATH:`pwd`/flutter/bin"
# Add Flutter to your path permanently (macOS/Linux)
echo 'export PATH="$PATH:[PATH_TO_FLUTTER_GIT_DIRECTORY]/flutter/bin"' >> ~/.zshrc
source ~/.zshrc
# Add Flutter to your path permanently (Windows)
# Update your system's environment variables
```_
### Platform Setup
Android Setup
```bash
# Install Android Studio
# Download from https://developer.android.com/studio
# Set up Android emulator
# Open Android Studio > AVD Manager > Create Virtual Device
# Accept Android licenses
flutter doctor --android-licenses
```_
iOS Setup (nur macOS)
```bash
# Install Xcode
# Download from Mac App Store
# Install CocoaPods
sudo gem install cocoapods
# Set up iOS simulator
open -a Simulator
```_
### Flutter Doctor
```bash
# Check your environment and see a report of the status of your Flutter installation
flutter doctor
# Verbose output
flutter doctor -v
```_
Gestartet
### Neues Projekt erstellen
```bash
# Create a new Flutter project
flutter create my_app
# Navigate to the project directory
cd my_app
# Create a project with a specific organization
flutter create --org com.example my_app
# Create a project with a specific template
flutter create -t module my_module
```_
### Run the App
```bash
# Run the app on an available device
flutter run
# Run on a specific device
flutter run -d chrome
flutter run -d 'iPhone 12'
# Run in release mode
flutter run --release
# Run with hot reload
# Press 'r' in the terminal
# Run with hot restart
# Press 'R' in the terminal
```_
### Projektstruktur
Kernkonzepte
Dart Language Basics¶
```dart // Variables var name = 'Flutter'; String language = 'Dart'; int year = 2017; double version = 2.12; bool isAwesome = true;
// Functions int add(int a, int b) { return a + b; }
// Arrow syntax int multiply(int a, int b) => a * b;
// Classes class Person { String name; int age;
Person(this.name, this.age);
void sayHello() { print('Hello, my name is $name and I am $age years old.'); } }
// Asynchronous programming
Future
void main() async { var person = Person('John Doe', 30); person.sayHello();
print('Fetching data...'); var data = await fetchData(); print(data); } ```_
Alles ist ein Widget¶
```dart import 'package:flutter/material.dart';
void main() { runApp( MaterialApp( home: Scaffold( appBar: AppBar( title: Text('My First Flutter App'), ), body: Center( child: Text('Hello, Flutter!'), ), ), ), ); } ```_
BuildContext¶
```dart // BuildContext provides information about the location of a widget in the widget tree. // It is used to access theme data, navigation, and other inherited widgets.
class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { return RaisedButton( onPressed: () { Scaffold.of(context).showSnackBar( SnackBar(content: Text('Button pressed')), ); }, child: Text('Press Me'), ); } } ```_
Stateless vs. Stateful Widgets¶
```dart // StatelessWidget: A widget that does not require mutable state. class MyStatelessWidget extends StatelessWidget { final String title;
MyStatelessWidget({required this.title});
@override Widget build(BuildContext context) { return Text(title); } }
// StatefulWidget: A widget that has mutable state. class MyStatefulWidget extends StatefulWidget { @override _MyStatefulWidgetState createState() => _MyStatefulWidgetState(); }
class _MyStatefulWidgetState extends State
void _incrementCounter() { setState(() { _counter++; }); }
@override Widget build(BuildContext context) { return Column( children: [ Text('Counter: $counter'), RaisedButton( onPressed: _incrementCounter, child: Text('Increment'), ), ], ); } } ```
Widgets
Basic Widgets¶
```dart import 'package:flutter/material.dart';
class BasicWidgets extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Basic Widgets')), body: SingleChildScrollView( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Text Text('This is a Text widget', style: TextStyle(fontSize: 18)), SizedBox(height: 20),
// Icon
Icon(Icons.favorite, color: Colors.red, size: 30),
SizedBox(height: 20),
// Image
Image.network('https://flutter.dev/images/flutter-logo-sharing.png'),
SizedBox(height: 20),
// Asset Image
Image.asset('assets/images/logo.png'),
SizedBox(height: 20),
// Button
RaisedButton(
onPressed: () {},
child: Text('RaisedButton'),
),
SizedBox(height: 10),
FlatButton(
onPressed: () {},
child: Text('FlatButton'),
),
SizedBox(height: 10),
IconButton(
onPressed: () {},
icon: Icon(Icons.thumb_up),
),
SizedBox(height: 20),
// TextField
TextField(
decoration: InputDecoration(
labelText: 'Enter your name',
border: OutlineInputBorder(),
),
),
SizedBox(height: 20),
// Checkbox
CheckboxListTile(
title: Text('Accept terms and conditions'),
value: true,
onChanged: (value) {},
),
SizedBox(height: 20),
// Radio
RadioListTile(
title: Text('Option 1'),
value: 1,
groupValue: 1,
onChanged: (value) {},
),
SizedBox(height: 20),
// Switch
SwitchListTile(
title: Text('Enable notifications'),
value: true,
onChanged: (value) {},
),
SizedBox(height: 20),
// Slider
Slider(
value: 0.5,
onChanged: (value) {},
),
SizedBox(height: 20),
// Progress Indicator
CircularProgressIndicator(),
SizedBox(height: 10),
LinearProgressIndicator(),
],
),
),
);
} } ```_
Material Komponenten¶
```dart import 'package:flutter/material.dart';
class MaterialComponents extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Material Components')), drawer: Drawer( child: ListView( children: [ DrawerHeader(child: Text('Drawer Header')), ListTile(title: Text('Item 1')), ListTile(title: Text('Item 2')), ], ), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Card Card( child: Padding( padding: EdgeInsets.all(16.0), child: Text('This is a Card'), ), ), SizedBox(height: 20),
// Chip
Chip(
avatar: CircleAvatar(child: Text('A')),
label: Text('Chip'),
),
SizedBox(height: 20),
// DataTable
DataTable(
columns: [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Name')),
],
rows: [
DataRow(cells: [DataCell(Text('1')), DataCell(Text('John'))]),
DataRow(cells: [DataCell(Text('2')), DataCell(Text('Jane'))]),
],
),
SizedBox(height: 20),
// SnackBar
RaisedButton(
onPressed: () {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('This is a SnackBar')),
);
},
child: Text('Show SnackBar'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
],
),
);
} } ```_
In den Warenkorb
Single-Child Layout Widgets¶
```dart import 'package:flutter/material.dart';
class SingleChildLayouts extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Single-Child Layouts')), body: Column( children: [ // Container Container( color: Colors.blue, padding: EdgeInsets.all(16.0), margin: EdgeInsets.all(16.0), child: Text('Container'), ),
// Center
Center(
child: Text('Center'),
),
// Padding
Padding(
padding: EdgeInsets.all(16.0),
child: Text('Padding'),
),
// Align
Align(
alignment: Alignment.bottomRight,
child: Text('Align'),
),
// SizedBox
SizedBox(
width: 200,
height: 100,
child: Card(child: Center(child: Text('SizedBox'))),
),
// AspectRatio
AspectRatio(
aspectRatio: 16 / 9,
child: Container(color: Colors.green),
),
// ConstrainedBox
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 200, maxHeight: 100),
child: Container(color: Colors.red),
),
],
),
);
} } ```_
Multi-Child Layout Widgets¶
```dart import 'package:flutter/material.dart';
class MultiChildLayouts extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Multi-Child Layouts')), body: Column( children: [ // Row Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [Text('Row 1'), Text('Row 2'), Text('Row 3')], ),
// Column
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text('Column 1'), Text('Column 2'), Text('Column 3')],
),
// Stack
Stack(
children: [
Container(width: 100, height: 100, color: Colors.red),
Container(width: 80, height: 80, color: Colors.green),
Container(width: 60, height: 60, color: Colors.blue),
],
),
// ListView
Expanded(
child: ListView(
children: [
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
],
),
),
// GridView
Expanded(
child: GridView.count(
crossAxisCount: 2,
children: List.generate(4, (index) => Center(child: Text('Item $index'))),
),
),
],
),
);
} } ```_
Navigation
Navigator 1.0 (Imperativ)¶
```dart // Navigate to a new screen Navigator.push( context, MaterialPageRoute(builder: (context) => DetailsScreen()), );
// Navigate back Navigator.pop(context);
// Navigate with data Navigator.push( context, MaterialPageRoute( builder: (context) => DetailsScreen(item: item), ), );
// Receive data from a screen final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => SelectionScreen()), );
// Send data back Navigator.pop(context, 'Yes'); ```_
Navigator 2.0 (Declarative)¶
```dart // pubspec.yaml dependencies: flutter: sdk: flutter go_router: ^3.0.0
// main.dart import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp.router( routeInformationParser: _router.routeInformationParser, routerDelegate: _router.routerDelegate, ); }
final _router = GoRouter( routes: [ GoRoute( path: '/', builder: (context, state) => HomeScreen(), ), GoRoute( path: '/details/:id', builder: (context, state) => DetailsScreen(id: state.params['id']!), ), ], ); }
// Navigate with go_router context.go('/details/123'); context.push('/details/456'); ```_
Staatliche Verwaltung
Provider¶
```dart // pubspec.yaml dependencies: provider: ^6.0.0
// main.dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart';
void main() { runApp( ChangeNotifierProvider( create: (context) => Counter(), child: MyApp(), ), ); }
class Counter with ChangeNotifier { int _count = 0; int get count => _count;
void increment() { _count++; notifyListeners(); } }
// Usage in a widget
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Provider Example')),
body: Center(
child: Text('Count: ${context.watch
BLoC (Business Logic Component)¶
```dart // pubspec.yaml dependencies: flutter_bloc: ^8.0.0
// counter_event.dart abstract class CounterEvent {} class Increment extends CounterEvent {}
// counter_bloc.dart import 'package:bloc/bloc.dart'; import 'counter_event.dart';
class CounterBloc extends Bloc
// main.dart import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
void main() { runApp( BlocProvider( create: (context) => CounterBloc(), child: MyApp(), ), ); }
// Usage in a widget
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('BLoC Example')),
body: Center(
child: BlocBuilder
Riverpod¶
```dart // pubspec.yaml dependencies: flutter_riverpod: ^1.0.0
// main.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateProvider((ref) => 0);
void main() { runApp(ProviderScope(child: MyApp())); }
// Usage in a widget class CounterScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: Text('Riverpod Example')),
body: Center(
child: Text('Count: $count'),
),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.state).state++,
child: Icon(Icons.add),
),
);
} } ```_
Vernetzung
http Package¶
```dart // pubspec.yaml dependencies: http: ^0.13.0
// services/api_service.dart import 'package:http/http.dart' as http; import 'dart:convert';
class ApiService { Future
dio Package¶
```dart // pubspec.yaml dependencies: dio: ^4.0.0
// services/api_service.dart import 'package:dio/dio.dart';
class ApiService { final dio = Dio();
Future
In der Tat
Shared_preferences¶
```dart // pubspec.yaml dependencies: shared_preferences: ^2.0.0
// utils/storage.dart import 'package:shared_preferences/shared_preferences.dart';
class Storage {
Future
Future
sqflite¶
```dart // pubspec.yaml dependencies: sqflite: ^2.0.0 path: ^1.8.0
// services/database_service.dart import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart';
class DatabaseService { late Database _database;
Future
Future
Future>> getUsers() async {
return await database.query('users');
}
}
```
In den Warenkorb
Implicit Animations¶
```dart class ImplicitAnimation extends StatefulWidget { @override _ImplicitAnimationState createState() => _ImplicitAnimationState(); }
class _ImplicitAnimationState extends State
@override Widget build(BuildContext context) { return GestureDetector( onTap: () => setState(() => isBig = !_isBig), child: AnimatedContainer( duration: Duration(seconds: 1), width: _isBig ? 200 : 100, height: _isBig ? 200 : 100, color: _isBig ? Colors.blue : Colors.red, ), ); } } ```
Explicit Animations¶
```dart class ExplicitAnimation extends StatefulWidget { @override _ExplicitAnimationState createState() => _ExplicitAnimationState(); }
class _ExplicitAnimationState extends State
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
_animation = Tween
@override void dispose() { _controller.dispose(); super.dispose(); }
@override Widget build(BuildContext context) { return Container( width: animation.value, height: _animation.value, color: Colors.green, ); } } ```
Integration von Plattformen
MethodChannel¶
```dart // Dart side import 'package:flutter/services.dart';
const platform = MethodChannel('com.example.myapp/channel');
Future
// Android side (MainActivity.java) import io.flutter.embedding.android.FlutterActivity; import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity { private static final String CHANNEL = "com.example.myapp/channel";
@Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { super.configureFlutterEngine(flutterEngine); new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) .setMethodCallHandler( (call, result) -> { if (call.method.equals("getBatteryLevel")) { // ... get battery level result.success(batteryLevel); } } ); } } ```_
Prüfung
Unit Testing¶
```dart // test/counter_test.dart import 'package:test/test.dart'; import 'package:my_app/counter.dart';
void main() { test('Counter value should be incremented', () { final counter = Counter(); counter.increment(); expect(counter.value, 1); }); } ```_
Widget Testing¶
```dart // test/widget_test.dart import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:my_app/main.dart';
void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { await tester.pumpWidget(MyApp());
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
}); } ```_
Integration Testing¶
```dart // test_driver/app_test.dart import 'package:flutter_driver/flutter_driver.dart'; import 'package:test/test.dart';
void main() { group('Counter App', () { FlutterDriver driver;
setUpAll(() async {
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
test('increments the counter', () async {
final counterTextFinder = find.byValueKey('counter');
final buttonFinder = find.byValueKey('increment');
expect(await driver.getText(counterTextFinder), '0');
await driver.tap(buttonFinder);
expect(await driver.getText(counterTextFinder), '1');
});
}); } ```_
Und was?
DevTools¶
```bash
Open DevTools from the terminal¶
flutter pub global activate devtools flutter pub global run devtools
Or from VS Code / Android Studio¶
```_
Logging¶
```dart import 'dart:developer' as developer;
void myFunction() { developer.log('This is a log message', name: 'my.app.category'); } ```_
Einsatz
Android¶
```bash
Build an APK¶
flutter build apk
Build an App Bundle¶
flutter build appbundle ```_
iOS¶
```bash
Build an IPA¶
flutter build ipa ```_
Web¶
```bash
Build for web¶
flutter build web ```_
oder Best Practices
- **Follow Effektive Dart Leitlinien*: Schreiben Sie sauber, pflegeleicht Dart-Code.
- **Organisieren Sie Ihre Projektstruktur*: Halten Sie Ihren Code organisiert und einfach zu navigieren.
- ** Verwenden Sie eine staatliche Verwaltungslösung*: Wählen Sie eine State Management Lösung, die der Komplexität Ihrer App entspricht.
- **Write Tests*: Schreibeinheit, Widget und Integrationstests, um sicherzustellen, dass Ihre App richtig funktioniert.
- Optimieren Sie die Leistung: Verwenden Sie DevTools, um Leistungsengpässe zu identifizieren und zu beheben.
- **Handle-Fehler anmutig*: Verwenden Sie Try-Catch Blöcke und Fehler Widgets, um Fehler zu handhaben.
Fehlerbehebung
Häufige Fragen¶
- **Platform-spezifische Probleme*: Überprüfen Sie Ihren Plattformaufbau (Android Studio, Xcode).
- ** Abhängigkeitskonflikte*: Führen Sie
flutter pub deps_ aus, um nach Abhängigkeitskonflikten zu suchen. Baufehler: Führen Sie __INLINE_CODE_36_ und dannflutter pub get_ aus, um Ihre Build-Dateien zu reinigen.
--
Zusammenfassung
Flutter ist ein leistungsstarkes und flexibles UI-Toolkit zum Aufbau hochwertiger, plattformübergreifender Anwendungen. Die wichtigsten Funktionen sind:
- Fast Development: Heißes Nachladen ermöglicht es Ihnen, Änderungen sofort zu sehen.
- **Expressive UI*: Bauen Sie schöne und benutzerdefinierte UIs mit einem reichen Satz von Widgets.
- Native Performance: Flutter-Apps werden auf nativen Code kompiliert und bieten hervorragende Leistungen.
- **Single Codebase*: Einmal schreiben, auf Handy, Web und Desktop laufen.
- **Growing Community*: Eine große und aktive Gemeinschaft bietet Unterstützung und ein reiches Ökosystem an Paketen.
Flutter ist eine ausgezeichnete Wahl für Entwickler, die schöne, leistungsstarke Anwendungen für mehrere Plattformen mit einer einzigen Codebasis erstellen möchten.