diff --git a/bibliography.bib b/bibliography.bib index 2676501..1c33397 100644 --- a/bibliography.bib +++ b/bibliography.bib @@ -162,4 +162,13 @@ isbn="978-981-15-1465-4" url = {https://nbn-resolving.org/urn:nbn:de:hbz:832-epub4-14989}, } +@Article{riverpodArticle, + author = {Greenberg, Benjamin L and Howell, Spencer L and Miles, Tucker R and Tang, Vicki and Troutman, Daniel N}, + journal = {Chancellor’s Honors Program Projects}, + title = {Attendio: Attendance Tracking Made Simple}, + year = {2021}, + url = {https://trace.tennessee.edu/utk_chanhonoproj/2432}, + urldate = {2022-01-30}, +} + @Comment{jabref-meta: databaseType:bibtex;} diff --git a/chapters/basics/state-management.tex b/chapters/basics/state-management.tex index 36f0544..1103230 100644 --- a/chapters/basics/state-management.tex +++ b/chapters/basics/state-management.tex @@ -103,6 +103,7 @@ Der innere Aufbau der \ac{bloc} ist explizit nicht vorgeschrieben, dient aber da Jede Seite (engl. Screen) sollte dabei exakt einem \ac{bloc} zugeordnet sein. Damit die Widgets auf diesen \ac{bloc} zugreifen können, müssen diese \texttt{injectable} sein - also zwischen mehreren Widgets geteilt. Dies kann unter anderem mit den bereits in \autoref{chap:included} vorgestellten Ansätzen umgesetzt werden. \subsection{Provider} +\label{sec:provider} Provider ist eine Bibliothek, die auf dem \texttt{InheritedWidget}-Ansatz (siehe \autoref{sec:inheritedWidget}) beruht. Dabei vereinfacht die Bibliothek die Benutzung und Erstellung von Klassen, die Zustände verwalten, und kombiniert das \texttt{InheritedWidget}-Konzept unter anderem mit der \texttt{ChangeNotifer}-Klasse. \autocite{stateManagementThesis} @@ -152,12 +153,46 @@ Die nachgelagerten Widgets können dabei, die Zustands-Klasse durch eine einfach \subsection{Riverpod} -Riverpod baut auf dem bereits vorgestellten Provider-Konzept auf, ergänzt es aber mit weiteren Funktionalitäten. Ein großer Unterschied liegt auch darin, dass hier Provider nicht in den Widget-Baum integriert werden müssen. Zudem ist es hier anders als bei der Provider-Bibliothek möglich, mehrere Provider vom gleichen Klassentyp zu unterscheiden. Hier wird nämlich nicht der Klassentyp zum Abruf der Zustands-Klasse im Widget verwendet, sondern eine Variable. Wie diese im Widget abgerufen wird, ist dabei von den Entwickelenden zu entscheiden. Denkbar sind hier beispielsweise das Verwenden einer globalen Variable oder einer Dependency-Injection-Lösung wie \texttt{get\_it}. +Riverpod baut auf dem bereits vorgestellten Provider-Konzept auf, ergänzt es aber mit weiteren Funktionalitäten. Ein großer Unterschied liegt auch darin, dass hier Provider nicht in den Widget-Baum integriert werden müssen. Zudem ist es hier anders als bei der Provider-Bibliothek möglich, mehrere Provider vom gleichen Klassentyp zu unterscheiden. Hier wird nämlich nicht der Klassentyp zum Abruf der Zustands-Klasse im Widget verwendet, sondern eine Variable. Wie diese im Widget abgerufen wird, ist dabei von den Entwickelenden zu entscheiden. Denkbar sind hier beispielsweise das Verwenden einer globalen Variable oder einer Dependency-Injection-Lösung wie \texttt{get\_it}. Damit wird auch ermöglicht, dass Riverpod im Vergleich zu Provider keine Abhängigkeit zum Flutter-Framework hat und somit eine reine Dart-Bibliothek ist. \autocite[S.8]{riverpodArticle} +Durch diese Unabhängigkeit vom Widget-Tree und dem Flutter-Framework kann hier auf das sogenannte \textit{Nesting} verzichtet werden. Dieses wird bei Provider benötigt, um Provider zu initialisieren, die von anderen Providern abhängen. Riverpod nutzt hier stattdessen eine Methode, mit der bei der Erstellung eines Providers andere Provider gelesen werden können. +\begin{lstlisting}[caption={Zustandsklasse in Riverpod}, label={lst:StateNotifier}] +class UserStore extends StateNotifier { + UserStore(User initialState) : super(initialState); + + changeFirstName(String newName) { + state = User(newName); + } +} +\end{lstlisting} + + +Für die Zustandsklassen selber gibt Riverpod eine eigene Strukur vor. Die Zustandsklassen erben die generische Klasse \texttt{StateNotifier}. Dabei wird über das Generic festgelegt, welchen Datentyp der Zustand haben soll. Dieser Zustand wird dann der Klasse als vererbte Variable zur Verfügung gestellt. Bei Änderung des Zustands reicht es somit aus, den Inhalt dieser Variable neu zu setzen wie in \autoref{lst:StateNotifier} gezeigt wird. Die Benutzeroberfläche greift dabei ausschließlich auf die Zustands-Variable direkt zu. Die Zustandsklasse ist nur dafür zuständig, Methoden zur Änderung dieses Zustands zur Verfügung zu stellen. + +Riverpod akzeptiert neben diesen Zustandsklassen auch die im Provider-Kapitel (siehe \autoref{sec:provider}) vorgestellen Event-Emitter wie beispielsweise \texttt{ChangeNotifier}. + +Da wie bereits erwähnt, Riverpod keine Flutter-Bibliothek ist und somit nicht wie Provider \texttt{InheritedWidget} zum Aktualisiern von referenzierenden Widgets benutzt, unterstützt sie von Haus aus noch nicht die Nutzung innerhalb eines Widgets. Um dies jedoch zu ermöglichen, besteht die Wahl zwischen zwei Ansätzen, die sich nur semantisch unterscheiden. + +\begin{lstlisting}[caption={ConsumerWidget}, label={lst:ConsumerWidget}] +final userStoreProvider = StateNotifierProvider((ref) => UserStore()); + +class ConsumingWidget extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final userStore = ref.watch(userStoreProvider); + return Text(userStore?.state.firstName); + } +} +\end{lstlisting} + + +Bei \texttt{flutter\_riverpod} werden die bereits eingeführten Widget-Typen \texttt{StatefulWidget} und \texttt{StatelessWidget} durch neue Typen ergänzt beziehungsweise ersetzt. Einer dieser neuen Typen ist \texttt{ConsumerWidget}. Durch das Erben von dieser Klasse, wird der \texttt{build}-Methode des Widgets eine neue Variable ergänzt, über die der Zustand von Riverpod-Providern abgefragt werden kann, wie in \autoref{lst:ConsumerWidget} zu sehen ist. Die hier verwendete \texttt{watch}-Methode bewirkt, dass das Widget neu gebaut wird, wenn sich der betreffende Provider ändert. \subsection{Redux} + + \subsection{GetIt} \subsection{MobX}