Flutter 101

Projektentwicklung mit Flutter

© Dominik Schumann - 2023 - fv.doryphmo.com

Wer bin ich?

  • Name: Dominik Schumann
  • Job: Software Engineer
  • Arbeitgeber: Maibornwolff
  • Abschluss: Bachelor of Science @ HWR
© Dominik Schumann - 2023 - fv.doryphmo.com

Wichtige Links

Flutter Documentation Our Repo
© Dominik Schumann - 2023 - fv.doryphmo.com

Kontakt

e_schumannd@doz.hwr-berlin.de

© Dominik Schumann - 2023 - fv.doryphmo.com

Introduction

© Dominik Schumann - 2023 - fv.doryphmo.com

Warum Flutter?

  • Cross Platform
  • echte native Apps
  • Schnelles Prototyping
  • Ein-Komponent Architektur
© Dominik Schumann - 2023 - fv.doryphmo.com

Platformen

Mittlerweile auf folgenden Platformen verfügbar:

  • Android
  • iOS
  • Web
  • Windows Apps
  • Linux
  • macOS
© Dominik Schumann - 2023 - fv.doryphmo.com

Einige Facts zu Flutter

  • Wird mit Dart entwickelt, Googles eigene Sprache
  • Ist eine native Anwendung, profitiert von nativem Code
  • innerhalb von Sekunden ist neuer Code in laufender Anwendung integriert
© Dominik Schumann - 2023 - fv.doryphmo.com

Entwicklung mit Flutter

© Dominik Schumann - 2023 - fv.doryphmo.com

Widgets

  • Die Komponente in Flutter
  • alles besteht aus Widgets
© Dominik Schumann - 2023 - fv.doryphmo.com
Ändern von Stateful Widgets Stateless Widgets
Parametern ✔️ ✔️
© Dominik Schumann - 2023 - fv.doryphmo.com
class Test extends StatelessWidget{
    final bool changeable;
    
    Test({
        required this.changeable,
    });

    @override
    Widget build(BuildContext context) {
        return changeable? Text('a') : Text('b');
    }
}

Das gilt genauso auch für Stateful Widgets

© Dominik Schumann - 2023 - fv.doryphmo.com
Ändern von Stateful Widgets Stateless Widgets
Parametern ✔️ ✔️
Membern ✔️ ❌
© Dominik Schumann - 2023 - fv.doryphmo.com
class Test extends StatelessWidget{
    bool changeable = true;
    ...

    return ElevatedButton(
        onPressed: () => changeable = !changeable,
        child: changeable ? Text('a') : Text('b'),
        // Text Content will always stay a
    );
}
© Dominik Schumann - 2023 - fv.doryphmo.com
class Test extends StatefulWidget {
    @override
    State<Test> createState() => _TestState();
}

class _TestState extends StatelessWidget{
    bool _changeable = true;
    ...

    return ElevatedButton(
        onPressed: () => 
            setState(() => _changeable = !_changeable),
        child: _changeable ? Text('a') : Text('b'),
        // Text Content will change on press
    );
}
© Dominik Schumann - 2023 - fv.doryphmo.com
Ändern von Stateful Widgets Stateless Widgets
Parametern ✔️ ✔️
Membern ✔️ ❌
© Dominik Schumann - 2023 - fv.doryphmo.com

Unser Repo

https://tinyurl.com/it2020-fv

© Dominik Schumann - 2023 - fv.doryphmo.com

1. Aufgabe

Baut einen weiteren Button ein, der die Anzahl auf dem Screen verkleinert. Baut den Text in eigenes unter Widget.

Widgets Catalog: https://docs.flutter.dev/development/ui/widgets

Helpful Widgets: Row, Elevated Button

© Dominik Schumann - 2023 - fv.doryphmo.com

© Dominik Schumann - 2023 - fv.doryphmo.com

© Dominik Schumann - 2023 - fv.doryphmo.com

Problem:

Wir haben nun ein Widget in der Mitte das sich um die Verarbeitung der Daten kümmert.

© Dominik Schumann - 2023 - fv.doryphmo.com

Lösung:

Eine Bibliothek die sich für uns um das State Management kümmert

© Dominik Schumann - 2023 - fv.doryphmo.com

State Management mit Bloc

© Dominik Schumann - 2023 - fv.doryphmo.com

Streams

  • stellen unendliche Datenströme dar
  • ein listen informiert über neuen Input
© Dominik Schumann - 2023 - fv.doryphmo.com

Was ist Bloc?

  • Bloc nutzt Streams für zwei Zwecke:
    • Input von Events (Trigger)
    • Output von States (View)
  • Ein Bloc ist die Verarbeitungs Einheit zwischen State und Event
© Dominik Schumann - 2023 - fv.doryphmo.com

© Dominik Schumann - 2023 - fv.doryphmo.com

Was brauchen wir für Bloc?

  • Event Klassen
  • State Klassen
  • Bloc
  • Interface in der UI
© Dominik Schumann - 2023 - fv.doryphmo.com

Event Klasse

abstract class CounterEvent extends Equatable {
  const CounterEvent();

  @override
  List<Object> get props => [];
} 

class CounterIncrement extends CounterEvent {}
© Dominik Schumann - 2023 - fv.doryphmo.com

State Klasse

abstract class CounterState extends Equatable {
  final int count;
  const CounterState({required this.count});

  @override
  List<Object> get props => [count];
}

class CounterInitial extends CounterState {
  const CounterInitial() : super(count: 0);
}

class CounterChanged extends CounterState {
  const CounterChanged({required super.count});
}
© Dominik Schumann - 2023 - fv.doryphmo.com

Bloc

part 'counter_event.dart';
part 'counter_state.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(const CounterInitial()) {
    on<CounterIncrement>((event, emit) => 
        emit(CounterChanged(count: state.count + 1)));
  }
}
© Dominik Schumann - 2023 - fv.doryphmo.com

Interface UI und Bloc

Coding

© Dominik Schumann - 2023 - fv.doryphmo.com

Was ist der BuildContext?

  • enthält Informationen über bisher gebaute Widgets
  • enthält Informationen über den Screen/Device
© Dominik Schumann - 2023 - fv.doryphmo.com
Widget build(BuildContext context) {
  return BlocProvider(
    create: (context) => Bloc(),
    child:  ElevatedButton(
        onPressed: () => BlocProvider.of<Bloc>(context).add(A()),
        // ERROR: Bloc not Provided in context
        child: const Text('Increment'),
    ), // ElevatedButton
  ) // BlocProvider
}
© Dominik Schumann - 2023 - fv.doryphmo.com

Wie kann man das umgehen?

Widget build(BuildContext context) {
  return BlocProvider(
    create: (context) => Bloc(),
    child:  Builder(
      builder: (buttonContext) {
        return ElevatedButton(
            onPressed: () => BlocProvider.of<Bloc>(buttonContext).add(A()),
            child: const Text('Increment'),
        ); // ElevatedButton
      }
    ),// Builder
  )// BlocProvider
}
© Dominik Schumann - 2023 - fv.doryphmo.com

Interface UI und Bloc

Coding

© Dominik Schumann - 2023 - fv.doryphmo.com

3. Aufgabe

Baut einen Drawer in eure Applikation lasst in diesem einen Namen anzeigen, der auf der Seite verändert werden kann.

Helpful Widgets: Drawer, DrawerHeader, TextField

© Dominik Schumann - 2023 - fv.doryphmo.com

Der Inhalt des Widgets ändert sich auf Grundlage der hereingegebenen Widgets. Falls sich changeable ändern sollte, wird auch ein neuer Wert zurückgegeben in Runtime

Darüberhinaus soll ein Widget eigentlich keine mutable Values haben

Wichtig ist im Kopf zu behalten, wenn ein Member sich ändert baut sich das gesamte Widget neu. Versucht am ehesten Stateless Widgets zu verwenden

Aufgabe danach besprechen, Ergebnisse der Studenten zusammen anschauen und evtl. Probleme besprechen evtl. um die 20min

Vor allem herausstellen, dass es ein großes Problem ist, dass es ein Widget ist

Interface um zwischen Bloc und UI zu kommunizieren

Equatable: - macht ein Deep Equal anstand ein object equal - sorgt dafür, dass ein Event mit den selvben Werten nicht ausversehen doppelt triggered, gerade bei States umso wichtiger

Context Stolperfalle einbauen

Da der Context alle Informationen über bisher gebaute Widgets beinhaltet. Erwartet BlocProvider.of(context) den Bloc findet ihn aber nicht Context beinhaltet noch nicht diese Informationen

Aufgabe danach besprechen, Ergebnisse der Studenten zusammen anschauen und evtl. Probleme besprechen evtl. um die 20min