Arsitektur Flutter: Penyedia vs BLoC

Diterbitkan: 2020-04-17

Menulis aplikasi dengan Flutter menciptakan peluang besar untuk memilih arsitektur. Seperti yang sering terjadi, jawaban terbaik untuk pertanyaan "Yang mana yang harus saya pilih?" adalah "Tergantung". Ketika Anda mendapatkan jawaban itu, Anda dapat yakin bahwa Anda menemukan seorang ahli dalam pemrograman.

Dalam artikel ini, kita akan membahas layar paling populer di aplikasi seluler dan menerapkannya di dua arsitektur Flutter paling populer: Provider dan BLoC . Hasilnya, kita akan mempelajari pro dan kontra dari setiap solusi, yang akan membantu kita memilih arsitektur Flutter yang tepat untuk modul atau aplikasi berikutnya.

Pengantar singkat untuk arsitektur Flutter

Memilih arsitektur untuk proyek pengembangan Flutter sangat penting, terutama karena fakta bahwa kita berurusan dengan paradigma pemrograman deklaratif yang kurang umum digunakan. Ini benar-benar mengubah pendekatan untuk mengelola sate yang akrab dengan pengembang Android atau iOS asli, menulis kode secara imperatif. Data yang tersedia di satu tempat dalam aplikasi tidak begitu mudah diperoleh di tempat lain. Kami tidak memiliki referensi langsung ke tampilan lain di pohon, dari mana kami bisa mendapatkan status mereka saat ini.

Apa itu Penyedia di Flutter

Seperti namanya, Provider adalah arsitektur Flutter yang menyediakan model data terkini ke tempat yang kita butuhkan saat ini. Ini berisi beberapa data dan memberi tahu pengamat ketika terjadi perubahan. Di Flutter SDK, jenis ini disebut ChangeNotifier . Agar objek bertipe ChangeNotifier tersedia untuk widget lain, kita memerlukan ChangeNotifierProvider . Ini menyediakan objek yang diamati untuk semua keturunannya. Objek yang dapat menerima data saat ini adalah Consumer , yang memiliki instance ChangeNotifier dalam parameter fungsi build -nya yang dapat digunakan untuk mengumpankan tampilan berikutnya dengan data.

Apa itu BLoC di Flutter

Komponen Logika Bisnis adalah arsitektur Flutter yang jauh lebih mirip dengan solusi populer di seluler seperti MVP atau MVVM. Ini memberikan pemisahan lapisan presentasi dari aturan logika bisnis. Ini adalah aplikasi langsung dari pendekatan deklaratif yang sangat ditekankan oleh Flutter yaitu UI = f (state) . BLoC adalah tempat acara dari antarmuka pengguna pergi. Di dalam lapisan ini, sebagai akibat dari penerapan aturan bisnis ke peristiwa tertentu, BLoC merespons dengan status tertentu, yang kemudian kembali ke UI. Ketika lapisan tampilan menerima status baru, ia membangun kembali tampilannya sesuai dengan apa yang dibutuhkan oleh status saat ini.

Ikon layanan pengembangan

Ingin tahu tentang pengembangan Flutter?

Lihat solusi kami

Cara membuat daftar di Flutter

Daftar yang dapat digulir mungkin adalah salah satu tampilan paling populer di aplikasi seluler. Oleh karena itu, memilih arsitektur Flutter yang tepat mungkin penting di sini. Secara teoritis, menampilkan daftar itu sendiri tidak sulit. Situasi menjadi lebih rumit ketika, misalnya, kami menambahkan kemampuan untuk melakukan tindakan tertentu pada setiap elemen. Itu akan menyebabkan perubahan di berbagai tempat di aplikasi. Dalam daftar kami, kami akan dapat memilih masing-masing elemen, dan masing-masing elemen yang dipilih akan ditampilkan dalam daftar terpisah di layar yang berbeda.

Membuat daftar di Flutter

Oleh karena itu, kita harus menyimpan elemen yang telah dipilih, agar dapat ditampilkan di layar baru. Selain itu, kita perlu membangun kembali tampilan setiap kali kotak centang diketuk, untuk benar-benar menampilkan centang / hapus centang.

Model item daftar terlihat sangat sederhana:

 kelas Media Sosial {
 int.id;
 Judul string;
 Ikon stringAset;
 bool adalah Favorit;

 Media sosial(
     {@memerlukan this.id,
     @required this.title,
     @required this.iconAsset,
     this.isFavorit = false});

 void setFavorit(bool adalahFavorit) {
   this.isFavorite = isFavorit;
 }
}

Cara membuat daftar dengan Penyedia

Dalam pola Provider, model di atas harus disimpan dalam sebuah objek. Objek harus memperluas ChangeNotifier agar dapat mengakses SocialMedia dari tempat lain di aplikasi.

 class SocialMediaModel memperluas ChangeNotifier {
 final List<SocialMedia> _socialMedia = [ /* beberapa objek media sosial */ ];

 UnmodifiableListView<SocialMedia> dapatkan favorit {
   return UnmodifiableListView(_socialMedia.where((item) => item.isFavourite));
 }

 UnmodifiableListView<SocialMedia> dapatkan semua {
   mengembalikan UnmodifiableListView(_socialMedia);
 }


void setFavourite(int itemId, bool isChecked) {
 _media sosial
     .firstWhere((item) => item.id == itemId)
     .setFavorit(dicentang);
 notifyListeners();
}

Setiap perubahan pada objek ini, yang akan memerlukan pembangunan kembali pada tampilan, harus ditandai menggunakan notifyListeners() . Dalam kasus metode setFavourite() untuk menginstruksikan Flutter untuk merender ulang fragmen UI, yang akan mengamati perubahan pada objek ini.

Sekarang kita dapat melanjutkan untuk membuat daftar. Untuk mengisi ListView dengan elemen, kita perlu masuk ke objek SocialMediaModel , yang menyimpan daftar semua elemen. Anda dapat melakukannya dengan dua cara:

  • Provider.of<ModelType>(konteks, dengarkan: false)
  • Konsumen

Yang pertama menyediakan objek yang diamati dan memungkinkan kita untuk memutuskan apakah tindakan yang dilakukan pada objek harus membangun kembali widget saat ini, menggunakan parameter listen . Perilaku ini akan berguna dalam kasus kami.

 class SocialMediaListScreen memperluas StatelessWidget {
 SocialMediaListScreen();

 @mengesampingkan
 Pembuatan widget (konteks BuildContext) {
   var socialMedia = Provider.of<SocialMediaModel>(context, listen: false);

   kembalikan Tampilan Daftar(
     anak-anak: socialMedia.all
         .map((item) => Kotak CentangSocialMediaItem(item: item))
         .toList(),
   );
 }
}

Kami membutuhkan daftar semua media sosial tetapi tidak perlu membangun kembali seluruh daftar. Mari kita lihat seperti apa tampilan widget item daftar.

 class CheckboxSocialMediaItem memperluas StatelessWidget {
 item Media Sosial terakhir;

 CheckboxSocialMediaItem({Key key, @required this.item}) : super(key: key);

 @mengesampingkan
 Pembuatan widget (konteks BuildContext) {
   kembali Padding (
     padding: const EdgeInsets.all(Dimens.paddingDefault),
     anak: baris (
       anak-anak: [
         Konsumen<SocialMediaModel>(
           pembangun: (konteks, model, anak) {
             kembali kotak centang (
               nilai: item.isFavorit,
               onChanged: (diperiksa) =>
                   model.setFavorit(item.id, dicentang),
             );
           },
         ),
         ItemMedia Sosial(
           barang: barang,
         )
       ],
     ),
   );
 }
}

Kami mendengarkan perubahan nilai kotak centang dan memperbarui model berdasarkan status centang. Nilai kotak centang itu sendiri diatur menggunakan properti dari model data. Artinya, setelah dipilih, model akan mengubah bidang isFavourite menjadi true . Namun, tampilan tidak akan menampilkan perubahan ini sampai kami membangun kembali kotak centang. Di sini, objek Konsumen dilengkapi dengan bantuan. Ini menyediakan objek yang diamati dan membangun kembali semua turunannya setelah menerima informasi tentang perubahan model.

Sebaiknya tempatkan Konsumen hanya di tempat yang perlu memperbarui widget untuk menghindari tampilan pembangunan kembali yang tidak perlu. Harap dicatat bahwa jika, misalnya, pemilihan kotak centang akan memicu beberapa tindakan tambahan seperti mengubah judul item, Konsumen harus dipindahkan lebih tinggi di pohon widget, sehingga menjadi induk dari widget yang bertanggung jawab untuk menampilkan judul . Jika tidak, tampilan judul tidak akan diperbarui.

Membuat layar media sosial favorit akan terlihat serupa. Kami akan mendapatkan daftar item favorit menggunakan Provider .

 class FavoritListScreen memperluas StatelessWidget {
 FavoritListScreen();

 @mengesampingkan
 Pembuatan widget (konteks BuildContext) {
   var list = Provider.of<SocialMediaModel>(konteks, dengarkan: false).favorit;

   kembalikan Tampilan Daftar(
     anak-anak: daftar
         .map((item) => Padding(
             padding: const EdgeInsets.all(Dimens.paddingDefault),
             anak: SocialMediaItem(item: item)))
         .toList(),
   );
 }
}

Saat metode build dipanggil, Penyedia akan mengembalikan daftar media sosial favorit saat ini.

Cara membuat daftar dengan BLoC

Dalam aplikasi sederhana kami, kami memiliki dua layar sejauh ini. Masing-masing dari mereka akan memiliki objek BLoC sendiri. Namun, perlu diingat bahwa item yang dipilih di layar utama akan muncul di daftar media sosial favorit. Oleh karena itu, entah bagaimana kita harus mentransfer acara pemilihan kotak centang di luar layar. Solusinya adalah membuat objek BLoC tambahan yang akan menangani peristiwa yang memengaruhi status banyak layar. Sebut saja BLoC global. Kemudian, objek BLoC yang ditetapkan ke layar individual akan mendengarkan perubahan status BLoC global dan meresponsnya.

Sebelum Anda membuat objek BLoC , Anda harus terlebih dahulu memikirkan tentang peristiwa apa yang dapat dikirim oleh tampilan ke lapisan BLoC dan status apa yang akan ditanggapinya. Dalam kasus BLoC global, peristiwa dan statusnya adalah sebagai berikut:

 kelas abstrak SocialMediaEvent {}

class CheckboxChecked memperluas SocialMediaEvent {
 bo terakhir diperiksa;
 int itemId akhir;

 CheckboxChecked(this.isChecked, this.itemId);
}


kelas abstrak SocialMediaState {}

class ListPresented memperluas SocialMediaState {
 daftar terakhir Daftar<SocialMedia>;

 ListPresented(ini.daftar);
}

Acara CheckboxChecked harus dalam BLoC global, karena akan memengaruhi status banyak layar – bukan hanya satu. Ketika datang ke negara bagian, kami memiliki satu di mana daftar siap ditampilkan. Dari sudut pandang BLoC global, tidak perlu membuat lebih banyak negara bagian. Kedua layar harus menampilkan daftar dan BLoC individual yang didedikasikan untuk layar tertentu harus menanganinya. Implementasi BLoC global itu sendiri akan terlihat seperti ini:

 class SocialMediaBloc memperluas Bloc<SocialMediaEvent, SocialMediaState> {
 repositori SimpleSocialMediaRepository terakhir;

 SocialMediaBloc(ini.repositori);

 @mengesampingkan
 SocialMediaState dapatkan initialState => ListPresented(repository.getSocialMedia);

 @mengesampingkan
 Aliran<SocialMediaState> mapEventToState(SocialMediaEvent event) async* {
   if (acara dicentang) {
     hasilkan _mapCheckboxCheckedToState(acara);
   }
 }

 SocialMediaState _mapCheckboxCheckedToState(CheckboxChecked event) {
   final updatedList = (sebutkan sebagai ListPresented).list;
   daftar terupdate
       .firstWhere((item) => item.id == event.itemId)
       .setFavorit(event.isChecked);
   mengembalikan ListPresented(daftar yang diperbarui);
 }
}

Status awal adalah ListPresented – kami berasumsi bahwa kami telah menerima data dari repositori. Kami hanya perlu menanggapi satu peristiwa – Kotak centangDicentang . Jadi kami akan memperbarui elemen yang dipilih menggunakan metode setFavourite dan mengirim daftar baru yang dibungkus dengan status ListPresented .

Sekarang kita perlu mengirim acara CheckboxChecked saat mengetuk kotak centang. Untuk melakukan ini, kita memerlukan instance SocialMediaBloc di tempat kita dapat melampirkan callback onChanged . Kita bisa mendapatkan instance ini menggunakan BlocProvider – terlihat mirip dengan Provider dari pola yang dibahas di atas. Agar BlocProvider seperti itu berfungsi, lebih tinggi di pohon widget, Anda harus menginisialisasi objek BLoC yang diinginkan. Dalam contoh kita, itu akan dilakukan dalam metode utama:

 void main() => runApp(BlocProvider(
   buat: (konteks) {
     kembalikan SocialMediaBloc(SimpleSocialMediaRepository());
   },
   anak: ArchitecturesSampleApp()));

Berkat ini, dalam kode daftar utama, kita dapat dengan mudah memanggil BLoC menggunakan BlocProvider.of () dan mengirim acara ke sana menggunakan metode add :

 class SocialMediaListScreen memperluas StatefulWidget {
 _SocialMediaListState createState() => _SocialMediaListState();
}

class _SocialMediaListState memperluas Status<SocialMediaListScreen> {
 @mengesampingkan
 Pembuatan widget (konteks BuildContext) {
   kembalikan BlocBuilder<SocialMediaListBloc, SocialMediaListState>(
     pembangun: (konteks, status) {
       if (status adalah MainListLoaded) {
         kembalikan Tampilan Daftar(
           anak-anak: state.socialMedia
               .map((item) => Kotak CentangSocialMediaItem(
                     barang: barang,
                     onCheckboxChanged: (diperiksa) =>
                         BlocProvider.of<SocialMediaBloc>(konteks)
                             .add(CheckboxChecked(isChecked, item.id)),
                   ))
               .toList(),
         );
       } kalau tidak {
         return Center(anak: Teks(Strings.emptyList));
       }
     },
   );
 }
}

Kami sudah memiliki propagasi acara CheckboxChecked ke BLoC , kami juga tahu bagaimana BLoC akan merespons acara semacam itu. Tapi sebenarnya... apa yang akan menyebabkan daftar dibangun kembali dengan kotak centang yang sudah dipilih? Global BLoC tidak mendukung perubahan status daftar, karena ditangani oleh objek BLoC individual yang ditetapkan ke layar. Solusinya adalah mendengarkan BLoC global yang disebutkan sebelumnya untuk mengubah status dan merespons sesuai dengan status ini. Di bawah, BLoC didedikasikan untuk daftar media sosial utama dengan kotak centang:

 kelas SocialMediaListBloc
   memperluas Bloc<SocialMediaListEvent, SocialMediaListState> {
 blok utama SocialMediaBloc terakhir;

 SocialMediaListBloc({@required this.mainBloc}) {
   mainBloc.listen((status) {
     if (status adalah ListPresented) {
       add(ScreenStart(negara.daftar));
     }
   });
 }

 @mengesampingkan
 SocialMediaListState dapatkan initialState => MainListEmpty();

 @mengesampingkan
 Aliran<SocialMediaListState> mapEventToState(
     Acara SocialMediaListEvent) async* {
   switch (event.runtimeType) {
     kasus LayarMulai:
       hasil MainListLoaded((event sebagai ScreenStart).list);
       merusak;
   }
 }
}

Saat SocialMediaBloc mengembalikan status ListPresented , SocialMediaListBloc akan diberi tahu. Perhatikan bahwa ListPresented menyampaikan daftar. Itu yang berisi informasi terbaru tentang memeriksa item dengan kotak centang.

Demikian pula, kita dapat membuat BLoC yang didedikasikan untuk layar media sosial favorit:

 class FavouritesListBloc memperluas Bloc<FavoritesListEvent, FavoritListSate> {
 blok utama SocialMediaBloc terakhir;

 FavoritListBloc({@required this.mainBloc}) {
   mainBloc.listen((status) {
     if (status adalah ListPresented) {
       add(FavoritLayarStart(negara.daftar));
     }
   });
 }

 @mengesampingkan
 FavouritesListSate dapatkan initialState => FavouritesListEmpty();

 @mengesampingkan
 Stream<FavoritesListSate> mapEventToState(Acara FavoritListEvent) async* {
   if (acara adalah FavoritScreenStart) {
     var favouritesList = event.list.where((item) => item.isFavourite).toList();
     hasilkan FavoritListLoaded(daftar favorit);
   }
 }
}

Mengubah status di BLoC global menghasilkan pengaktifan acara FavoritScreenStart dengan daftar saat ini. Kemudian, item yang ditandai sebagai favorit difilter dan daftar tersebut ditampilkan di layar.

Cara membuat formulir dengan banyak bidang di Flutter

Formulir yang panjang bisa jadi rumit, terutama ketika persyaratan mengasumsikan varian validasi yang berbeda, atau beberapa perubahan di layar setelah memasukkan teks. Pada layar contoh, kami memiliki formulir yang terdiri dari beberapa bidang dan tombol "BERIKUTNYA". Bidang akan secara otomatis memvalidasi dan tombol dinonaktifkan hingga formulir sepenuhnya valid. Setelah mengklik tombol, layar baru akan terbuka dengan data yang dimasukkan dalam formulir.

Kami harus memvalidasi setiap bidang dan memeriksa seluruh koreksi formulir untuk mengatur status tombol dengan benar. Kemudian, data yang dikumpulkan perlu disimpan untuk layar berikutnya.

Membuat formulir dengan banyak bidang di Flutter

Cara membuat formulir dengan banyak bidang dengan Penyedia

Dalam aplikasi kami, kami memerlukan ChangeNotifier kedua, yang didedikasikan untuk layar info pribadi. Oleh karena itu, kita dapat menggunakan MultiProvider , di mana kita menyediakan daftar objek ChangeNotifier . Mereka akan tersedia untuk semua keturunan MultiProvider .

 class ArchitecturesSampleApp memperluas StatelessWidget {
 repositori SimpleSocialMediaRepository terakhir;

 ArchitecturesSampleApp({Kunci kunci, this.repository}) : super(kunci: kunci);

 @mengesampingkan
 Pembuatan widget (konteks BuildContext) {
   kembalikan MultiPenyedia(
     penyedia: [
       ChangeNotifierProvider<SocialMediaModel>(
         buat: (konteks) => SocialMediaModel(repositori),
       ),
       ChangeNotifierProvider<PersonalDataNotifier>(
         buat: (konteks) => PersonalDataNotifier(),
       )
     ],
     anak: MaterialApp(
       judul: Strings.architecturesSampleApp,
       debugShowCheckedModeBanner: salah,
       rumah: StartScreen(),
       rute: <String, WidgetBuilder>{
         Routes.socialMedia: (konteks) => SocialMediaScreen(),
         Routes.favorites: (konteks) => FavoritScreen(),
         Routes.personalDataForm: (konteks) => PersonalDataScreen(),
         Routes.personalDataInfo: (konteks) => PersonalDataInfoScreen()
       },
     ),
   );
 }
}

Dalam hal ini, PersonalDataNotifier akan bertindak sebagai lapisan logika bisnis – ia akan memvalidasi bidang, memiliki akses ke model data untuk pembaruannya, dan memperbarui bidang tempat tampilan akan bergantung.

Formulir itu sendiri adalah API yang sangat bagus dari Flutter, di mana kita dapat secara otomatis melampirkan validasi menggunakan validator properti dan menyimpan data dari formulir ke model menggunakan panggilan balik onSaved . Kami akan mendelegasikan aturan validasi ke PersonalDataNotifier dan ketika formulir sudah benar, kami akan meneruskan data yang dimasukkan ke dalamnya.

Hal terpenting di layar ini adalah mendengarkan perubahan di setiap bidang dan mengaktifkan atau menonaktifkan tombol, tergantung pada hasil validasi. Kami akan menggunakan callback onChange dari objek Form . Di dalamnya, pertama-tama kita akan memeriksa status validasi dan kemudian meneruskannya ke PersonalDataNotifier .

 Membentuk(
 kunci: _formKey,
 validasi otomatis: benar,
 onChanged: () => _onFormChanged(personalDataNotifier),
 anak:

void _onFormChanged(PersonalDataNotifier personalDataNotifier) ​​{
 var isValid = _formKey.currentState.validate();
 personalDataNotifier.onFormChanged(isValid);
}

Di PersonalDataNotifier , kami akan menyiapkan variabel isFormValid . Kami akan memodifikasinya (jangan lupa untuk memanggil notifyListeners() ) dan dalam tampilan, kami akan mengubah status tombol tergantung pada nilainya. Ingatlah untuk mendapatkan instance Notifier dengan parameter listen: true – jika tidak, tampilan kita tidak akan dibangun kembali dan status tombol akan tetap tidak berubah.

 var personalDataNotifier = Provider.of<PersonalDataNotifier>(konteks, dengar: benar);

Sebenarnya, mengingat fakta bahwa kita menggunakan personalDataNotifier di tempat lain, di mana memuat ulang tampilan tidak diperlukan, baris di atas tidak optimal dan seharusnya parameter listen disetel ke false . Satu-satunya hal yang ingin kami muat ulang adalah tombolnya, sehingga kami dapat membungkusnya dalam Consumer klasik :

 Konsumen<PersonalDataNotifier>(
 pembangun: (konteks, pemberi tahu, anak) {
   kembali RaisedButton(
     anak: Teks(Strings.addressNext),
     onPressed: notifier.isFormValid
         ? /* tindakan saat tombol diaktifkan */
         : nol,
     warna: Colors.blue,
     dinonaktifkanWarna: Warna.abu-abu,
   );
 },
)

Berkat ini, kami tidak memaksa komponen lain untuk memuat ulang setiap kali kami menggunakan pemberi notifikasi.

Dalam tampilan menampilkan data pribadi, tidak akan ada masalah lagi – kami memiliki akses ke PersonalDataNotifier dan dari sana, kami dapat mengunduh model yang diperbarui.

Cara membuat formulir dengan banyak bidang dengan BLoC

Untuk layar sebelumnya kami membutuhkan dua objek BLoC . Jadi ketika kita menambahkan "layar ganda" lainnya, kita akan memiliki empat sekaligus. Seperti halnya Provider , kita dapat menanganinya dengan MultiBlocProvider , yang bekerja hampir sama.

 batal main() => runApp(
     MultiBlocProvider(penyedia: [
       Penyedia Blok(
         buat: (konteks) => SocialMediaBloc(SimpleSocialMediaRepository()),
       ),
       Penyedia Blok(
           buat: (konteks) => SocialMediaListBloc(
               mainBloc: BlocProvider.of<SocialMediaBloc>(konteks))),
       Penyedia Blok(
         buat: (konteks) => PersonalDataBloc(),
       ),
       Penyedia Blok(
         buat: (konteks) => PersonalDataInfoBloc(
             mainBloc: BlocProvider.of<PersonalDataBloc>(konteks)),
       )
     ], anak: ArchitecturesSampleApp()),
   );

Seperti dalam pola BLoC , yang terbaik adalah memulai dengan kemungkinan status dan tindakan.

 kelas abstrak PersonalDataState {}

class NextButtonDisabled memperluas PersonalDataState {}

class NextButtonEnabled memperluas PersonalDataState {}

class InputFormCorrect memperluas PersonalDataState {
 model PersonalData akhir;

 InputFormCorrect(model ini.);
}

Apa yang berubah pada layar ini adalah status tombol. Oleh karena itu kita membutuhkan negara bagian yang terpisah untuk itu. Selain itu, status InputFormCorrect akan memungkinkan kami mengirim data yang telah dikumpulkan oleh formulir.

 kelas abstrak PersonalDataEvent {}

class FormInputChanged memperluas PersonalDataEvent {
 hasil akhir adalahValid;
 FormInputChanged(this.isValid);
}

class FormCorrect memperluas PersonalDataEvent {
 formulirData Pribadi akhir;

 FormCorrect(this.formData);
}

Mendengarkan perubahan dalam formulir sangat penting, oleh karena itu acara FormInputChanged . Ketika formulir sudah benar, acara FormCorrect akan dikirim.

Dalam hal validasi, ada perbedaan besar di sini jika Anda membandingkannya dengan Penyedia. Jika kami ingin menyertakan semua logika validasi di lapisan BLoC , kami akan memiliki banyak peristiwa untuk setiap bidang. Selain itu, banyak negara bagian akan memerlukan tampilan untuk menampilkan pesan validasi.

Ini, tentu saja, mungkin tetapi akan seperti pertarungan melawan TextFormField API alih-alih menggunakan manfaatnya. Oleh karena itu, jika tidak ada alasan yang jelas, Anda dapat meninggalkan validasi di lapisan tampilan.

Status tombol akan tergantung pada status yang dikirim ke tampilan oleh BLoC :

 BlocBuilder<PersonalDataBloc, PersonalDataState>(
   pembangun: (konteks, status) {
 kembali RaisedButton(
   anak: Teks(Strings.addressNext),
   onPressed: status adalah NextButtonEnabled
       ? /* tindakan saat tombol diaktifkan */
       : nol,
   warna: Colors.blue,
   dinonaktifkanWarna: Warna.abu-abu,
 );
})

Penanganan dan pemetaan acara ke status di PersonalDataBloc adalah sebagai berikut:

 @mengesampingkan
Stream<PersonalDataState> mapEventToState(PersonalDataEvent event) async* {
 if (acara adalah FormCorrect) {
   hasilkan InputFormCorrect(event.formData);
 } else if (event adalah FormInputChanged) {
   hasilkan mapFormInputChangedToState(acara);
 }
}

PersonalDataState mapFormInputChangedToState(Acara FormInputChanged) {
 if (event.isValid) {
   kembali NextButtonEnabled();
 } kalau tidak {
   kembalikan NextButtonDisabled();
 }
}

Adapun layar dengan ringkasan data pribadi, situasinya mirip dengan contoh sebelumnya. BLoC yang terpasang pada layar ini akan mengambil informasi model dari BLoC dari layar formulir.

 kelas PersonalDataInfoBloc
   memperluas Bloc<PersonalDataInfoEvent, PersonalDataInfoState> {
 PersonalDataBloc mainBloc terakhir;

 PersonalDataInfoBloc({@required this.mainBloc}) {
   mainBloc.listen((status) {
     if (status adalah InputFormCorrect) {
       tambahkan(PersonalDataInfoScreenStart(negara.model));
     }
   });
 }

 @mengesampingkan
 PersonalDataInfoState dapatkan initialState => InfoEmpty();

 @mengesampingkan
 Aliran<PersonalDataInfoState> mapEventToState(PersonalDataInfoEvent event) async* {
   if (acara adalah PersonalDataInfoScreenStart) {
     hasilkan InfoLoaded(event.model);
   }
 }
}

Arsitektur Flutter: catatan untuk diingat

Contoh-contoh di atas sudah cukup untuk menunjukkan bahwa ada perbedaan yang jelas antara kedua arsitektur tersebut. BLoC memisahkan lapisan tampilan dari logika bisnis dengan sangat baik. Ini memerlukan reusability dan testability yang lebih baik. Tampaknya untuk menangani kasus sederhana, Anda perlu menulis lebih banyak kode daripada di Provider . Seperti yang Anda ketahui, dalam hal ini, arsitektur Flutter ini akan menjadi lebih berguna seiring dengan meningkatnya kompleksitas aplikasi.

Ikon bawa pulang

Ingin membangun aplikasi berorientasi masa depan untuk bisnis Anda?

Mari kita berhubungan

Penyedia juga memisahkan UI dari logika dengan baik dan tidak memaksa pembuatan status terpisah dengan setiap interaksi pengguna, yang berarti bahwa seringkali Anda tidak perlu menulis kode dalam jumlah besar untuk menangani kasus sederhana. Tetapi ini dapat menyebabkan masalah dalam kasus yang lebih kompleks.

Klik di sini untuk melihat keseluruhan proyek.