NyState
Pengantar
NyState adalah versi yang diperluas dari kelas State standar Flutter. Kelas ini menyediakan fungsionalitas tambahan untuk membantu mengelola state halaman dan widget Anda dengan cara yang lebih efisien.
Anda dapat berinteraksi dengan state persis seperti yang Anda lakukan dengan state Flutter biasa, tetapi dengan manfaat tambahan dari NyState.
Mari kita bahas cara menggunakan NyState.
Cara Menggunakan NyState
Anda dapat mulai menggunakan kelas ini dengan meng-extend-nya.
Contoh
class _HomePageState extends NyState<HomePage> {
@override
get init => () async {
};
@override
view(BuildContext context) {
return Scaffold(
body: Text("The page loaded")
);
}
Method init digunakan untuk menginisialisasi state halaman. Anda dapat menggunakan method ini sebagai async atau tanpa async dan di balik layar, ia akan menangani panggilan async dan menampilkan loader.
Method view digunakan untuk menampilkan UI halaman.
Membuat stateful widget baru dengan NyState
Untuk membuat stateful widget baru di Nylo Website, Anda dapat menjalankan perintah di bawah ini.
metro make:stateful_widget ProfileImage
Gaya Loading
Anda dapat menggunakan properti loadingStyle untuk mengatur gaya loading halaman Anda.
Contoh
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
};
loadingStyle default akan menjadi Widget loading Anda (resources/widgets/loader_widget.dart).
Anda dapat menyesuaikan loadingStyle untuk memperbarui gaya loading.
Berikut tabel untuk berbagai gaya loading yang dapat Anda gunakan: // normal, skeletonizer, none
| Gaya | Deskripsi |
|---|---|
| normal | Gaya loading default |
| skeletonizer | Gaya loading skeleton |
| none | Tanpa gaya loading |
Anda dapat mengubah gaya loading seperti ini:
@override
LoadingStyle get loadingStyle => LoadingStyle.normal();
// or
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer();
Jika Anda ingin memperbarui Widget loading di salah satu gaya, Anda dapat memasukkan child ke LoadingStyle.
@override
LoadingStyle get loadingStyle => LoadingStyle.normal(
child: Center(
child: Text("Loading..."),
),
);
// same for skeletonizer
@override
LoadingStyle get loadingStyle => LoadingStyle.skeletonizer(
child: Container(
child: PageLayoutForSkeletonizer(),
)
);
Sekarang, saat tab sedang loading, teks "Loading..." akan ditampilkan.
Contoh di bawah ini:
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")
);
}
...
}
Aksi State
Di Nylo, Anda dapat mendefinisikan aksi kecil di Widget Anda yang dapat dipanggil dari kelas lain. Ini berguna jika Anda ingin memperbarui state widget dari kelas lain.
Pertama, Anda harus mendefinisikan aksi Anda di widget. Ini bekerja untuk NyState dan 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);
},
};
}
Kemudian, Anda dapat memanggil aksi dari kelas lain menggunakan method stateAction.
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");
Jika Anda menggunakan stateActions dengan NyPage, Anda harus menggunakan path dari halaman tersebut.
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");
Ada juga kelas lain bernama StateAction, kelas ini memiliki beberapa method yang dapat Anda gunakan untuk memperbarui state widget Anda.
refreshPage- Segarkan halaman.pop- Pop halaman.showToastSorry- Tampilkan notifikasi toast sorry.showToastWarning- Tampilkan notifikasi toast warning.showToastInfo- Tampilkan notifikasi toast info.showToastDanger- Tampilkan notifikasi toast danger.showToastOops- Tampilkan notifikasi toast oops.showToastSuccess- Tampilkan notifikasi toast success.showToastCustom- Tampilkan notifikasi toast kustom.validate- Validasi data dari widget Anda.changeLanguage- Perbarui bahasa di aplikasi.confirmAction- Lakukan aksi konfirmasi.
Contoh
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",
);
}
}
Anda dapat menggunakan kelas StateAction untuk memperbarui state halaman/widget mana pun di aplikasi Anda selama widget tersebut dikelola state-nya.
Helper
Reboot
Method ini akan menjalankan ulang method init di state Anda. Berguna jika Anda ingin menyegarkan data di halaman.
Contoh
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 - Hapus halaman saat ini dari stack.
Contoh
class _HomePageState extends NyState<HomePage> {
popView() {
pop();
}
@override
Widget view(BuildContext context) {
return Scaffold(
body: InkWell(
onTap: popView,
child: Text("Pop current view")
)
);
}
showToast
Tampilkan notifikasi toast pada context.
Contoh
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
Helper validate melakukan pemeriksaan validasi pada data.
Anda dapat mempelajari lebih lanjut tentang validator di sini.
Contoh
class _HomePageState extends NyState<HomePage> {
TextEditingController _textFieldControllerEmail = TextEditingController();
handleForm() {
String textEmail = _textFieldControllerEmail.text;
validate(rules: {
"email address": [textEmail, "email"]
}, onSuccess: () {
print('passed validation')
});
}
changeLanguage
Anda dapat memanggil changeLanguage untuk mengubah file json /lang yang digunakan di perangkat.
Pelajari lebih lanjut tentang lokalisasi di sini.
Contoh
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
Anda dapat menggunakan whenEnv untuk menjalankan fungsi ketika aplikasi Anda berada dalam keadaan tertentu.
Contoh: variabel APP_ENV di dalam file .env Anda diatur ke 'developing', APP_ENV=developing.
Contoh
class _HomePageState extends NyState<HomePage> {
TextEditingController _textEditingController = TextEditingController();
@override
get init => () {
whenEnv('developing', perform: () {
_textEditingController.text = 'test-email@gmail.com';
});
};
lockRelease
Method ini akan mengunci state setelah fungsi dipanggil, hanya setelah method selesai barulah ia mengizinkan pengguna membuat permintaan berikutnya. Method ini juga akan memperbarui state, gunakan isLocked untuk memeriksa.
Contoh terbaik untuk menunjukkan lockRelease adalah membayangkan kita memiliki layar login ketika pengguna mengetuk 'Login'. Kita ingin melakukan panggilan async untuk login pengguna tetapi kita tidak ingin method dipanggil berkali-kali karena dapat membuat pengalaman yang tidak diinginkan.
Berikut contoh di bawah ini.
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"),
),
)
],
)
);
}
Setelah Anda mengetuk method _login, ia akan memblokir permintaan berikutnya sampai permintaan asli selesai. Helper isLocked('login_to_app') digunakan untuk memeriksa apakah tombol terkunci. Pada contoh di atas, Anda dapat melihat kami menggunakannya untuk menentukan kapan menampilkan Widget loading.
isLocked
Method ini akan memeriksa apakah state terkunci menggunakan helper lockRelease.
Contoh
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
Method view digunakan untuk menampilkan UI halaman.
Contoh
class _HomePageState extends NyState<HomePage> {
@override
Widget view(BuildContext context) {
return Scaffold(
body: Center(
child: Text("My Page")
)
);
}
}
confirmAction
Method confirmAction akan menampilkan dialog kepada pengguna untuk mengonfirmasi aksi.
Method ini berguna jika Anda ingin pengguna mengonfirmasi aksi sebelum melanjutkan.
Contoh
_logout() {
confirmAction(() {
// logout();
}, title: "Logout of the app?");
}
showToastSuccess
Method showToastSuccess akan menampilkan notifikasi toast sukses kepada pengguna.
Contoh
_login() {
...
showToastSuccess(
description: "You have successfully logged in"
);
}
showToastOops
Method showToastOops akan menampilkan notifikasi toast oops kepada pengguna.
Contoh
_error() {
...
showToastOops(
description: "Something went wrong"
);
}
showToastDanger
Method showToastDanger akan menampilkan notifikasi toast danger kepada pengguna.
Contoh
_error() {
...
showToastDanger(
description: "Something went wrong"
);
}
showToastInfo
Method showToastInfo akan menampilkan notifikasi toast info kepada pengguna.
Contoh
_info() {
...
showToastInfo(
description: "Your account has been updated"
);
}
showToastWarning
Method showToastWarning akan menampilkan notifikasi toast warning kepada pengguna.
Contoh
_warning() {
...
showToastWarning(
description: "Your account is about to expire"
);
}
showToastSorry
Method showToastSorry akan menampilkan notifikasi toast sorry kepada pengguna.
Contoh
_sorry() {
...
showToastSorry(
description: "Your account has been suspended"
);
}
isLoading
Method isLoading akan memeriksa apakah state sedang loading.
Contoh
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
Method afterLoad dapat digunakan untuk menampilkan loader sampai state selesai 'loading'.
Anda juga dapat memeriksa key loading lain menggunakan parameter loadingKey afterLoad(child: () {}, loadingKey: 'home_data').
Contoh
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
Method afterNotLocked akan memeriksa apakah state terkunci.
Jika state terkunci, ia akan menampilkan widget [loading].
Contoh
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
Anda dapat menggunakan afterNotNull untuk menampilkan widget loading sampai variabel telah diatur.
Bayangkan Anda perlu mengambil akun pengguna dari DB menggunakan panggilan Future yang mungkin memakan waktu 1-2 detik, Anda dapat menggunakan afterNotNull pada nilai tersebut sampai Anda memiliki datanya.
Contoh
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
Anda dapat beralih ke state 'loading' dengan menggunakan setLoading.
Parameter pertama menerima bool apakah sedang loading atau tidak, parameter berikutnya memungkinkan Anda mengatur nama untuk state loading, contoh: setLoading(true, name: 'refreshing_content');.
Contoh
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")
);
}