Arbeiten mit Listen in Flutter-Anwendungen (Teil 2) / Sudo Null IT News

Im letzten Artikel habe ich meine Erfahrungen mit Listen geteilt. Es wurde besprochen, wie man Daten lädt, filtert, aktualisiert und andere Aktionen in der Liste durchführt. Wie Sie dem Artikel entnehmen können, erfordert die Implementierung solcher Funktionen, dass der Entwickler eine ziemlich große Menge an Code schreibt und Szenarien implementiert, die nicht immer offensichtlich sind.

In diesem Artikel zeige ich Ihnen, wie Sie die Erstellung von Controllern für die Verwaltung von Listen vereinfachen können meine Bibliothek. Darin habe ich versucht, meine Ideen und Entwicklungen zur Implementierung des Listencontrollers zu bündeln. Als Beispiel erstellen wir eine einfache Listenanwendung, die Daten beim Scrollen lädt.

Die Hauptfunktionen der Bibliothek:

Ein wichtiger Punkt ist, dass die Bibliothek architekturunabhängig ist: Sie kann mit beliebigen Widgets verwendet werden und ist mit jedem Zustandsverwaltungsansatz kompatibel (sei es ValueNotifier, Bloc oder jeder andere Ansatz).

Die Arbeit mit der Bibliothek ist sehr einfach. Zuerst müssen Sie einen Klassen-Stub erstellen, der als Listen-Controller dient. Verbinden Sie dann mit dieser Klasse die von der Bibliothek bereitgestellten Mixins, die für die von Ihnen benötigte Funktionalität verantwortlich sind. Und schließlich implementieren Sie in der Klasse die Funktionen, die für die Arbeit der verwendeten Mixins erforderlich sind.

Betrachten wir nun die Implementierung der Liste mit unendlichem Scrollen basierend auf dem StatefulWidget.

Fertige Anwendung

Lassen Sie uns eine neue Flutter-App erstellen.

> flattern create list_controller_example

Fügen wir dem Projekt die Bibliotheken list_controller und Equatable hinzu.

> cd list_controller_example > flatter pub add list_controller gleichbedeutend

Weiterhin werden wir nur mit der main.dart-Datei arbeiten. Lassen Sie uns den gesamten Inhalt durch Folgendes ersetzen:

import ‘Paket:gleichwertig/gleichwertig.dart’; import ‘paket:flutter/material.dart’; import ‘Paket:Listencontroller/Listencontroller.dart’; void main() { runApp(const MaterialApp( title: ‘List Controller Example’, home: MyHomePage(), )); } Klasse MyHomePage erweitert StatefulWidget { const MyHomePage({super.key}) : super(); @override State createState() => _MyHomePageState(); } class _MyHomePageState erweitert State { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text(‘List Controller Example’), ), body: Container() ); } }

Damit der Controller funktioniert, müssen einige Datenstrukturen implementiert werden.

Lassen Sie uns eine Klasse erstellen, um eine Anforderung zum Abrufen von Daten aus einer Quelle zu beschreiben.

Klasse ListQuery erweitert Equatable { const ListQuery ({this.weightGt = 0}); final int weightGt; @override List Requisiten abrufen => [weightGt]; }

In dieser Klasse wird der Parameter weightGt benötigt, um anzugeben, dass Datensätze aus der Datenquelle mit einer Gewichtung geladen werden sollen, die größer ist als die in diesem Parameter gespeicherte.

Als Nächstes müssen Sie eine Klasse erstellen, um den Zustand der Liste zu speichern. Die Bibliothek erlegt dieser Klasse keine Einschränkungen auf, stellt jedoch eine Klasse bereit, die für die meisten Szenarien geeignet ist. Wir werden es in unserer Anwendung verwenden.

Lassen Sie uns diese Klasse wie folgt konfigurieren.

typedef ListStateExample = ListState;

Hier ist int der Datentyp, durch den die Listeneinträge dargestellt werden.

Lassen Sie uns nun eine Klasse definieren, die das aus der Datenquelle geladene Ergebnis darstellt.

class LoadResult { const LoadResult({required this.records, required this.isFinalPage}); final List Datensätze; final bool isFinalPage; }

Records ist darin eine Liste geladener Datensätze. In diesem Fall meldet isFinalPage, ob das Ende der Liste erreicht ist.

Um die von uns benötigte Funktionalität zu implementieren, benötigen wir die folgenden Mixins: ListCore, RecordsLoader, KeysetPagination. Fügen wir sie der Klasse _MyHomePageState hinzu.

class _MyHomePageState erweitert State mit ListCore, RecordsLoader, KeysetPagination { …

Fügen Sie als Nächstes zu dieser Klasse hinzu:

  1. eine Variable zum Speichern des Zustands der Liste;
  2. Code zum Laden der ersten Datenseite;
  3. Aufruf der Close-Funktion des Controllers.

ListStateExample state = ListStateExample(query: const ListQuery()); // 1 @override void initState() { loadRecords(state.query); // 2 super.initState(); } @override void dispose() { closeList(); // 3 super.dispose(); }

Jetzt können wir die Funktionen implementieren, die erforderlich sind, damit die verbundenen Mixins funktionieren.

Beginnen wir mit dem RecordsLoader-Mixin. Lassen Sie uns den Code hinzufügen:

@override void onRecordsLoadStart({erforderliche ListQuery-Abfrage, erforderlicher LoadingKey loadingKey}) => setState(() { state = state.copyWith(stage: ListStage.loading()); }); @override Future performLoadQuery({erforderliche ListQuery-Abfrage, erforderlicher LoadingKey loadingKey}) async { await Future.delayed(const Duration(Millisekunden: 1500)); return LoadResult(records: List.generate(20, (i) => query.weightGt + i + 1), isFinalPage: query.weightGt >= 80, ); } @override void putLoadResultToState({erforderliche ListQuery-Abfrage, erforderliches LoadResult loadResult, erforderlicher LoadingKey loadingKey}) => setState(() { state = state.copyWith( records: [
…state.records,
…loadResult.records,
], Stufe: loadResult.isFinalPage ? ListStage.complete() : ListStage.idle(), ); });

Die Funktion onRecordsLoadStart wird aufgerufen, bevor das Laden der Daten beginnt. Meist ist es notwendig, den Status der darin enthaltenen Liste so zu ändern, dass der laufende Download angezeigt wird.

Wie Sie sehen können, haben viele Funktionen den Parameter loadingKey. In unserem Fall wird es nicht verwendet, dient aber ggf. dazu, verschiedene Downloads bei der Umsetzung komplexerer Szenarien zu identifizieren und zu synchronisieren.

In der Funktion performLoadQuery werden die Daten geladen. Zur Vereinfachung des Beispiels wird in unserem Fall einfach eine Liste mit einer Zahlenfolge generiert.

In der Funktion putLoadResultToState werden die geladenen Datensätze zum Status der Liste hinzugefügt und die für die Anzeige des Ladeindikators verantwortliche Variable zurückgesetzt.

Lassen Sie uns nun die Funktionen implementieren, die für das KeysetPagination-Mixin benötigt werden. Lassen Sie uns den Code hinzufügen:

@override ListStage getListStage(LoadingKey loadingKey) => state.stage; @override ListQuery buildNextPageQuery(LoadingKey loadingKey) => ListQuery(weightGt: state.records.last);

Die getListStage-Funktion gibt den Zustand zurück, in dem sich die Liste befindet.

Die Funktion buildNextPageQuery erstellt eine Abfrage, um die nächste Datenseite abzurufen. Diese Abfrage wird später an die Funktion performLoadQuery übergeben.

An diesem Punkt haben wir das Schreiben des List-Controller-Codes abgeschlossen. Fahren wir mit der Anzeige dieser Liste fort.

Lassen Sie uns die gesamte Build-Funktion durch Folgendes ersetzen:

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text(‘List Controller Example’), body: Stack( children: [
ListView.builder(
itemCount: state.records.length,
itemBuilder: (context, index) {
const recordsLoadThreshold = 1;
if (index >= state.records.length – recordsLoadThreshold) {
WidgetsBinding.instance.addPostFrameCallback((_) {
loadNextPage();
});
}
return ListTile(title: Text(state.records[index].toString(); }, ), if (state.isLoading) const Center(child: CircularProgressIndicator()), ], ), ); }

Wenn sich die Liste im Ladezustand befindet, wird eine Ladeanzeige über der Liste angezeigt. Wenn das Laden der Daten abgeschlossen ist, werden die Listenelemente angezeigt. Das Laden der nächsten Seite der Liste erfolgt durch Aufrufen von loadNextPage, nachdem der Benutzer die Liste vom Ende bis zur Position recordsLoadThreshold gescrollt hat.

Fazit

In dem Artikel haben wir uns mit dem Erstellen einer Liste mit unendlichem Scrollen befasst. Das obige Beispiel demonstriert nur die Grundfunktionen der Bibliothek. Für Funktionen wie Download abbrechen, fehlgeschlagenen Download wiederholen, Listendaten aktualisieren, siehe Seite.

Der Anwendungscode aus dem Artikel ist unter verfügbar Verknüpfung.

Similar Posts

Leave a Reply

Your email address will not be published.