NyState
Einleitung
NyState ist eine erweiterte Version der Standard-Flutter-State-Klasse. Sie bietet zusätzliche Funktionen, um den State Ihrer Seiten und Widgets effizienter zu verwalten.
Sie können mit dem State interagieren genau wie mit einem normalen Flutter-State, aber mit den zusätzlichen Vorteilen von NyState.
Schauen wir uns an, wie man NyState verwendet.
NyState verwenden
Sie können diese Klasse verwenden, indem Sie sie erweitern.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
get init => () async {
};
@override
view(BuildContext context) {
return Scaffold(
body: Text("The page loaded")
);
}
Die init-Methode wird verwendet, um den State der Seite zu initialisieren. Sie können diese Methode mit oder ohne async verwenden, und im Hintergrund wird der asynchrone Aufruf behandelt und ein Loader angezeigt.
Die view-Methode wird verwendet, um die UI der Seite anzuzeigen.
Ein neues Stateful Widget mit NyState erstellen
Um eine neue Seite in Nylo Website zu erstellen, können Sie den folgenden Befehl ausführen.
metro make:stateful_widget ProfileImage
Ladestil
Sie können die loadingStyle-Eigenschaft verwenden, um den Ladestil für Ihre Seite festzulegen.
Beispiel
class _ProfileImageState extends NyState<ProfileImage> {
@override
LoadingStyleType get loadingStyle => LoadingStyleType.normal();
@override
get init => () async {
await sleep(3); // simulate a network call for 3 seconds
};
Der Standard-loadingStyle wird Ihr Lade-Widget (resources/widgets/loader_widget.dart) sein.
Sie können den loadingStyle anpassen, um den Ladestil zu aktualisieren.
Hier ist eine Tabelle für die verschiedenen Ladestile, die Sie verwenden können: // normal, skeletonizer, none
| Stil | Beschreibung |
|---|---|
| normal | Standard-Ladestil |
| skeletonizer | Skeleton-Ladestil |
| none | Kein Ladestil |
Sie können den Ladestil wie folgt ändern:
@override
LoadingStyle get loadingStyle => LoadingStyle.normal();
// or
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer();
Wenn Sie das Lade-Widget in einem der Stile aktualisieren möchten, können Sie ein child an den LoadingStyle übergeben.
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
// same for skeletonizer
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer(
child: Container(
child: PageLayoutForSkeletonizer(),
)
);
Wenn der Tab lädt, wird der Text "Loading..." angezeigt.
Beispiel unten:
class _HomePageState extends NyState<HomePage> {
get init => () async {
await sleep(3); // simulate a network call for 3 seconds
};
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
@override
Widget view(BuildContext context) {
return Scaffold(
body: Text("The page loaded")
);
}
...
}
State-Aktionen
In Nylo können Sie kleine Aktionen in Ihren Widgets definieren, die von anderen Klassen aufgerufen werden können. Dies ist nützlich, wenn Sie den State eines Widgets von einer anderen Klasse aktualisieren möchten.
Zuerst müssen Sie Ihre Aktionen in Ihrem Widget definieren. Dies funktioniert für NyState und NyPage.
class _MyWidgetState extends NyState<MyWidget> {
@override
get init => () async {
// handle how you want to initialize the state
};
@override
get stateActions => {
"hello_world_in_widget": () {
print('Hello world');
},
"update_user_name": (User user) async {
// Example with data
_userName = user.name;
setState(() {});
},
"show_toast": (String message) async {
showToastSuccess(description: message);
},
};
}
Dann können Sie die Aktion von einer anderen Klasse mit der stateAction-Methode aufrufen.
stateAction('hello_world_in_widget', state: MyWidget.state);
// Another example with data
User user = User(name: "John Doe");
stateAction('update_user_name', state: MyWidget.state, data: user);
// Another example with data
stateAction('show_toast', state: MyWidget.state, data: "Hello world");
Wenn Sie stateActions mit einem NyPage verwenden, müssen Sie den Pfad der Seite verwenden.
stateAction('hello_world_in_widget', state: ProfilePage.path);
// Another example with data
User user = User(name: "John Doe");
stateAction('update_user_name', state: ProfilePage.path, data: user);
// Another example with data
stateAction('show_toast', state: ProfilePage.path, data: "Hello world");
Es gibt auch eine weitere Klasse namens StateAction, die einige Methoden hat, mit denen Sie den State Ihrer Widgets aktualisieren können.
refreshPage- Die Seite aktualisieren.pop- Die Seite entfernen.showToastSorry- Eine Sorry-Toast-Benachrichtigung anzeigen.showToastWarning- Eine Warnung-Toast-Benachrichtigung anzeigen.showToastInfo- Eine Info-Toast-Benachrichtigung anzeigen.showToastDanger- Eine Gefahr-Toast-Benachrichtigung anzeigen.showToastOops- Eine Oops-Toast-Benachrichtigung anzeigen.showToastSuccess- Eine Erfolgs-Toast-Benachrichtigung anzeigen.showToastCustom- Eine benutzerdefinierte Toast-Benachrichtigung anzeigen.validate- Daten aus Ihrem Widget validieren.changeLanguage- Die Sprache in der Anwendung aktualisieren.confirmAction- Eine Bestätigungsaktion ausführen.
Beispiel
class _UpgradeButtonState extends NyState<UpgradeButton> {
view(BuildContext context) {
return Button.primary(
onPressed: () {
StateAction.showToastSuccess(UpgradePage.state,
description: "You have successfully upgraded your account",
);
},
text: "Upgrade",
);
}
}
Sie können die StateAction-Klasse verwenden, um den State jeder Seite/jedes Widgets in Ihrer Anwendung zu aktualisieren, solange das Widget state-verwaltet ist.
Helfer
Reboot
Diese Methode führt die init-Methode in Ihrem State erneut aus. Dies ist nützlich, wenn Sie die Daten auf der Seite aktualisieren möchten.
Beispiel
class _HomePageState extends NyState<HomePage> {
List<User> users = [];
@override
get init => () async {
users = await api<ApiService>((request) => request.fetchUsers());
};
@override
Widget view(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Users"),
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
reboot(); // refresh the data
},
)
],
),
body: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Text(users[index].firstName);
}
),
);
}
}
Pop
pop - Die aktuelle Seite vom Stack entfernen.
Beispiel
class _HomePageState extends NyState<HomePage> {
popView() {
pop();
}
@override
Widget view(BuildContext context) {
return Scaffold(
body: InkWell(
onTap: popView,
child: Text("Pop current view")
)
);
}
showToast
Eine Toast-Benachrichtigung im Kontext anzeigen.
Beispiel
class _HomePageState extends NyState<HomePage> {
displayToast() {
showToast(
title: "Hello",
description: "World",
icon: Icons.account_circle,
duration: Duration(seconds: 2),
style: ToastNotificationStyleType.INFO // SUCCESS, INFO, DANGER, WARNING
);
}
@override
Widget view(BuildContext context) {
return Scaffold(
body: InkWell(
onTap: displayToast,
child: Text("Display a toast")
)
);
}
validate
Der validate-Helfer führt eine Validierungsprüfung auf Daten durch.
Sie können mehr über den Validator hier erfahren.
Beispiel
class _HomePageState extends NyState<HomePage> {
TextEditingController _textFieldControllerEmail = TextEditingController();
handleForm() {
String textEmail = _textFieldControllerEmail.text;
validate(rules: {
"email address": [textEmail, "email"]
}, onSuccess: () {
print('passed validation')
});
}
changeLanguage
Sie können changeLanguage aufrufen, um die json-/lang-Datei zu ändern, die auf dem Gerät verwendet wird.
Erfahren Sie mehr über Lokalisierung hier.
Beispiel
class _HomePageState extends NyState<HomePage> {
changeLanguageES() {
await changeLanguage('es');
}
@override
Widget view(BuildContext context) {
return Scaffold(
body: InkWell(
onTap: changeLanguageES,
child: Text("Change Language".tr())
)
);
}
whenEnv
Sie können whenEnv verwenden, um eine Funktion auszuführen, wenn sich Ihre Anwendung in einem bestimmten Zustand befindet.
Z.B. Ihre APP_ENV-Variable in Ihrer .env-Datei ist auf 'developing' gesetzt, APP_ENV=developing.
Beispiel
class _HomePageState extends NyState<HomePage> {
TextEditingController _textEditingController = TextEditingController();
@override
get init => () {
whenEnv('developing', perform: () {
_textEditingController.text = 'test-email@gmail.com';
});
};
lockRelease
Diese Methode sperrt den State, nachdem eine Funktion aufgerufen wurde, und erlaubt dem Benutzer erst dann nachfolgende Anfragen, wenn die Methode beendet ist. Diese Methode aktualisiert auch den State. Verwenden Sie isLocked, um den Status zu prüfen.
Das beste Beispiel, um lockRelease zu demonstrieren, ist sich vorzustellen, dass wir einen Login-Bildschirm haben und wenn der Benutzer auf 'Login' tippt. Wir möchten einen asynchronen Aufruf durchführen, um den Benutzer anzumelden, aber wir möchten nicht, dass die Methode mehrfach aufgerufen wird, da dies zu einem unerwünschten Erlebnis führen könnte.
Hier ist ein Beispiel unten.
class _LoginPageState extends NyState<LoginPage> {
_login() async {
await lockRelease('login_to_app', perform: () async {
await Future.delayed(Duration(seconds: 4), () {
print('Pretend to login...');
});
});
}
@override
Widget view(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (isLocked('login_to_app'))
AppLoader(),
Center(
child: InkWell(
onTap: _login,
child: Text("Login"),
),
)
],
)
);
}
Sobald Sie die _login-Methode aufrufen, blockiert sie alle nachfolgenden Anfragen, bis die ursprüngliche Anfrage beendet ist. Der isLocked('login_to_app')-Helfer wird verwendet, um zu prüfen, ob der Button gesperrt ist. Im obigen Beispiel können Sie sehen, dass wir damit bestimmen, wann unser Lade-Widget angezeigt wird.
isLocked
Diese Methode prüft, ob der State mit dem lockRelease-Helfer gesperrt ist.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
Widget view(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (isLocked('login_to_app'))
AppLoader(),
],
)
);
}
view
Die view-Methode wird verwendet, um die UI der Seite anzuzeigen.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
Widget view(BuildContext context) {
return Scaffold(
body: Center(
child: Text("My Page")
)
);
}
}
confirmAction
Die confirmAction-Methode zeigt dem Benutzer einen Dialog an, um eine Aktion zu bestätigen.
Diese Methode ist nützlich, wenn Sie möchten, dass der Benutzer eine Aktion bestätigt, bevor er fortfährt.
Beispiel
_logout() {
confirmAction(() {
// logout();
}, title: "Logout of the app?");
}
showToastSuccess
Die showToastSuccess-Methode zeigt dem Benutzer eine Erfolgs-Toast-Benachrichtigung an.
Beispiel
_login() {
...
showToastSuccess(
description: "You have successfully logged in"
);
}
showToastOops
Die showToastOops-Methode zeigt dem Benutzer eine Oops-Toast-Benachrichtigung an.
Beispiel
_error() {
...
showToastOops(
description: "Something went wrong"
);
}
showToastDanger
Die showToastDanger-Methode zeigt dem Benutzer eine Gefahr-Toast-Benachrichtigung an.
Beispiel
_error() {
...
showToastDanger(
description: "Something went wrong"
);
}
showToastInfo
Die showToastInfo-Methode zeigt dem Benutzer eine Info-Toast-Benachrichtigung an.
Beispiel
_info() {
...
showToastInfo(
description: "Your account has been updated"
);
}
showToastWarning
Die showToastWarning-Methode zeigt dem Benutzer eine Warnung-Toast-Benachrichtigung an.
Beispiel
_warning() {
...
showToastWarning(
description: "Your account is about to expire"
);
}
showToastSorry
Die showToastSorry-Methode zeigt dem Benutzer eine Sorry-Toast-Benachrichtigung an.
Beispiel
_sorry() {
...
showToastSorry(
description: "Your account has been suspended"
);
}
isLoading
Die isLoading-Methode prüft, ob der State lädt.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
Widget build(BuildContext context) {
if (isLoading()) {
return AppLoader();
}
return Scaffold(
body: Text("The page loaded", style: TextStyle(
color: colors().primaryContent
)
)
);
}
afterLoad
Die afterLoad-Methode kann verwendet werden, um einen Loader anzuzeigen, bis der State das 'Laden' beendet hat.
Sie können auch andere Ladeschlüssel mit dem Parameter loadingKey prüfen: afterLoad(child: () {}, loadingKey: 'home_data').
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
get init => () {
awaitData(perform: () async {
await sleep(4);
print('4 seconds after...');
});
};
@override
Widget build(BuildContext context) {
return Scaffold(
body: afterLoad(child: () {
return Text("Loaded");
})
);
}
afterNotLocked
Die afterNotLocked-Methode prüft, ob der State gesperrt ist.
Wenn der State gesperrt ist, wird das [loading]-Widget angezeigt.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: afterNotLocked('login', child: () {
return MaterialButton(
onPressed: () {
login();
},
child: Text("Login"),
);
}),
)
);
}
login() async {
await lockRelease('login', perform: () async {
await sleep(4);
print('4 seconds after...');
});
}
}
afterNotNull
Sie können afterNotNull verwenden, um ein Lade-Widget anzuzeigen, bis eine Variable gesetzt wurde.
Stellen Sie sich vor, Sie müssen das Konto eines Benutzers aus einer DB mit einem Future-Aufruf abrufen, der 1-2 Sekunden dauern könnte. Sie können afterNotNull auf diesen Wert anwenden, bis Sie die Daten haben.
Beispiel
class _HomePageState extends NyState<HomePage> {
User? _user;
@override
get init => () async {
_user = await api<ApiService>((request) => request.fetchUser()); // example
setState(() {});
};
@override
Widget build(BuildContext context) {
return Scaffold(
body: afterNotNull(_user, child: () {
return Text(_user!.firstName);
})
);
}
setLoading
Sie können mit setLoading in einen 'Lade'-Zustand wechseln.
Der erste Parameter akzeptiert einen bool für den Ladezustand, der nächste Parameter ermöglicht es Ihnen, einen Namen für den Ladezustand festzulegen, z.B. setLoading(true, name: 'refreshing_content');.
Beispiel
class _HomePageState extends NyState<HomePage> {
@override
get init => () async {
setLoading(true, name: 'refreshing_content');
await sleep(4);
setLoading(false, name: 'refreshing_content');
};
@override
Widget build(BuildContext context) {
if (isLoading(name: 'refreshing_content')) {
return AppLoader();
}
return Scaffold(
body: Text("The page loaded")
);
}