Flutter mimarisi: Sağlayıcı vs BLoC
Yayınlanan: 2020-04-17Flutter ile uygulama yazmak, mimariyi seçmek için harika fırsatlar yaratır. Çoğu zaman olduğu gibi, “Hangisini seçmeliyim?” Sorusuna en iyi cevap. "bağlıdır". Bu cevabı aldığınızda, programlama konusunda bir uzman bulduğunuzdan emin olabilirsiniz.
Bu yazımızda, mobil uygulamalardaki en popüler ekranları inceleyeceğiz ve bunları en popüler iki Flutter mimarisinde uygulayacağız: Provider ve BLoC . Sonuç olarak, bir sonraki modülümüz veya uygulamamız için doğru Flutter mimarisini seçmemize yardımcı olacak her bir çözümün artılarını ve eksilerini öğreneceğiz.
Flutter mimarisine kısa bir giriş
Bir Flutter geliştirme projesi için mimariyi seçmek, öncelikle daha az kullanılan, bildirime dayalı bir programlama paradigması ile uğraştığımız gerçeğinden dolayı büyük önem taşımaktadır. Bu, yerel Android veya iOS geliştiricilerinin aşina olduğu durumu yönetme yaklaşımını tamamen değiştirir ve kodu zorunlu olarak yazar. Uygulamada bir yerde bulunan verileri başka bir yerde elde etmek o kadar kolay değildir. Mevcut durumlarını elde edebileceğimiz ağaçtaki diğer görüşlere doğrudan referanslarımız yok.
Flutter'da Sağlayıcı Nedir?
Adından da anlaşılacağı gibi Provider , mevcut veri modelini şu anda ihtiyacımız olan yere sağlayan bir Flutter mimarisidir. Bazı veriler içerir ve bir değişiklik meydana geldiğinde gözlemcileri bilgilendirir. Flutter SDK'da bu türe ChangeNotifier adı verilir. ChangeNotifier türündeki nesnenin diğer widget'lar tarafından kullanılabilmesi için ChangeNotifierProvider'a ihtiyacımız var. Tüm torunları için gözlemlenen nesneler sağlar. Geçerli verileri alabilen nesne, derleme işlevinin parametresinde, sonraki görünümleri verilerle beslemek için kullanılabilen bir ChangeNotifier örneğine sahip olan Tüketici'dir .
Flutter'da BLoC Nedir?
Business Logic Components, MVP veya MVVM gibi mobildeki popüler çözümlere çok daha benzer bir Flutter mimarisidir. Sunum katmanının iş mantığı kurallarından ayrılmasını sağlar. Bu, Flutter'ın özellikle vurguladığı bildirimsel yaklaşımın doğrudan bir uygulamasıdır, yani UI = f (durum) . BLoC, kullanıcı arayüzündeki olayların gittiği bir yerdir. Bu katmanda, belirli bir olaya iş kurallarının uygulanmasının bir sonucu olarak, BLoC belirli bir durumla yanıt verir ve ardından kullanıcı arayüzüne geri döner. Görünüm katmanı yeni bir durum aldığında, görünümünü mevcut durumun gerektirdiği şekilde yeniden oluşturur.
Flutter gelişimini merak mı ediyorsunuz?
Çözümlerimizi görünFlutter'da bir liste nasıl oluşturulur?
Kaydırılabilir bir liste, muhtemelen mobil uygulamalardaki en popüler görünümlerden biridir. Bu nedenle, doğru Flutter mimarisini seçmek burada çok önemli olabilir. Teorik olarak, listenin kendisini görüntülemek zor değildir. Örneğin, her öğe üzerinde belirli bir eylemi gerçekleştirme yeteneği eklediğimizde durum daha da zorlaşıyor. Bu, uygulamada farklı yerlerde bir değişikliğe neden olmalıdır. Listemizde öğelerin her birini seçebileceğiz ve seçilenlerin her biri farklı bir ekranda ayrı bir listede görüntülenecektir.

Bu nedenle, yeni bir ekranda görüntülenebilmeleri için seçilen öğeleri saklamamız gerekir. Ek olarak, gerçekten kontrol / işareti kaldırmayı göstermek için onay kutusuna her dokunulduğunda görünümü yeniden oluşturmamız gerekecek.
Liste öğesi modeli çok basit görünüyor:
sınıf Sosyal Medya { int kimliği; Dize başlığı; String iconAsset; bool Favoridir; Sosyal medya( {@zorunlu this.id, @gerekli this.title, @ gerekli this.iconAsset, this.isFavourite = yanlış}); void setFavourite(bool isFavourite) { this.isFavourite = isFavourite; } }
Sağlayıcı ile bir liste nasıl oluşturulur
Sağlayıcı modelinde, yukarıdaki model bir nesnede saklanmalıdır. Nesne, uygulamadaki başka bir yerden SocialMedia'ya erişebilmek için ChangeNotifier'ı genişletmelidir.
class SocialMediaModel, ChangeNotifier'ı genişletir { final Liste<SocialMedia> _socialMedia = [ /* bazı sosyal medya nesneleri */ ]; DeğiştirilemezListView<SocialMedia> favorileri al { dönüş UnmodifiedListView(_socialMedia.where((item) => item.isFavourite)); } DeğiştirilemezListView<SocialMedia> tüm { döndürülemezListView(_socialMedia); } void setFavourite(int itemId, bool isChecked) { _sosyal medya .firstWhere((item) => item.id == itemId) .setFavourite(isChecked); notifyListeners(); }
Bu nesnede, görünümün yeniden oluşturulmasını gerektirecek herhangi bir değişiklik, notifyListeners() kullanılarak bildirilmelidir. Flutter'a UI parçasını yeniden oluşturma talimatı veren setFavourite() yöntemi durumunda, bu, bu nesnedeki değişikliği gözlemleyecektir.
Artık liste oluşturmaya geçebiliriz. ListView'i öğelerle doldurmak için, tüm öğelerin bir listesini saklayan SocialMediaModel nesnesine gitmemiz gerekecek. Bunu iki şekilde yapabilirsiniz:
- Provider.of<ModelType>(bağlam, dinle: yanlış)
- Tüketici
Birincisi, gözlemlenen nesneyi sağlar ve nesne üzerinde gerçekleştirilen eylemin, listen parametresini kullanarak geçerli parçacığı yeniden oluşturması gerekip gerekmediğine karar vermemize olanak tanır. Bu davranış bizim durumumuzda faydalı olacaktır.
class SocialMediaListScreen, StatelessWidget'ı genişletir { SocialMediaListScreen(); @geçersiz kıl Widget derlemesi(BuildContext bağlamı) { var socialMedia = Provider.of<SocialMediaModel>(context, dinle: false); ListView'ı döndür( çocuklar: sosyalMedia.all .map((item) => CheckboxSocialMediaItem(item: item)) .Listeye(), ); } }
Tüm sosyal medyanın bir listesine ihtiyacımız var ama tüm listeyi yeniden oluşturmaya gerek yok. Liste öğesi widget'ının nasıl göründüğüne bir göz atalım.
class CheckboxSocialMediaItem, StatelessWidget'ı genişletir { nihai Sosyal Medya öğesi; CheckboxSocialMediaItem({Key key, @required this.item}) : super(key: key); @geçersiz kıl Widget derlemesi(BuildContext bağlamı) { dönüş Dolgusu( dolgu: const EdgeInsets.all(Dimens.paddingDefault), çocuk: Satır( çocuklar: [ Tüketici<Sosyal MedyaModeli>( oluşturucu: (bağlam, model, alt) { dönüş Onay Kutusu( değer: item.isFavori, onChanged: (isChecked) => model.setFavourite(item.id, isChecked), ); }, ), Sosyal MedyaÖğesi( öğe: öğe, ) ], ), ); } }
Onay kutusunun değerindeki değişikliği dinliyoruz ve modeli kontrol durumuna göre güncelliyoruz. Onay kutusu değerinin kendisi, veri modelindeki özellik kullanılarak ayarlanır. Bu, seçimden sonra modelin isFavourite alanını true olarak değiştireceği anlamına gelir. Ancak, biz onay kutusunu yeniden oluşturana kadar görünüm bu değişikliği sunmayacaktır. Burada, bir Tüketici nesnesi yardımla birlikte gelir. Gözlemlenen nesneyi sağlar ve modeldeki değişiklik hakkında bilgi aldıktan sonra tüm torunlarını yeniden oluşturur.
Gereksiz yeniden oluşturma görünümlerinden kaçınmak için Tüketiciyi yalnızca widget'ı güncellemenin gerekli olduğu yere yerleştirmeye değer. Lütfen, örneğin, onay kutusu seçimi, öğenin başlığını değiştirmek gibi bazı ek eylemleri tetikleyecekse, Tüketicinin , başlığı görüntülemekten sorumlu pencere öğesinin ebeveyni olabilmesi için pencere öğesi ağacında daha yükseğe taşınması gerekeceğini unutmayın. . Aksi takdirde, başlık görünümü güncellenmeyecektir.
Favori bir sosyal medya ekranı oluşturmak benzer görünecektir. Sağlayıcı kullanarak favori öğelerin bir listesini alacağız.
class FavouritesListScreen, StatelessWidget'ı genişletir { FavorilerListScreen(); @geçersiz kıl Widget derlemesi(BuildContext bağlamı) { var list = Provider.of<SocialMediaModel>(context, listen: false).favourites; ListView'ı döndür( çocuklar: liste .map((item) => Doldurma( dolgu: const EdgeInsets.all(Dimens.paddingDefault), alt: SocialMediaItem(öğe: öğe))) .Listeye(), ); } }
Derleme yöntemi çağrıldığında, Sağlayıcı mevcut favori sosyal medya listesini döndürür.
BLoC ile bir liste nasıl oluşturulur
Basit uygulamamızda şu ana kadar iki ekranımız var. Her birinin kendi BLoC nesnesi olacaktır. Ancak, ana ekranda seçilen öğelerin favori sosyal medya listesinde görüneceğini unutmayın. Bu nedenle, onay kutusu seçim olaylarını bir şekilde ekranın dışına aktarmalıyız. Çözüm, birçok ekranın durumunu etkileyen olayları işleyecek ek bir BLoC nesnesi oluşturmaktır. Buna küresel BLoC diyelim . Ardından, bireysel ekranlara atanan BLoC nesneleri, global BLoC durumlarındaki değişiklikleri dinleyecek ve buna göre yanıt verecektir.
Bir BLoC nesnesi oluşturmadan önce, görünümün BLoC katmanına hangi olayları gönderebileceğini ve hangi durumlara yanıt vereceğini düşünmelisiniz. Global BLoC durumunda olaylar ve durumlar aşağıdaki gibi olacaktır:
soyut sınıf SocialMediaEvent {} class CheckboxChecked, SocialMediaEvent'i genişletir { final bool isChecked; son int itemId; CheckboxChecked(this.isChecked, this.itemId); } soyut sınıf SocialMediaState {} class ListPresented, SocialMediaState'i genişletir { nihai Liste<SocialMedia> listesi; ListPresented(this.list); }
CheckboxChecked olayı global BLoC içinde olmalıdır, çünkü yalnızca bir ekranın değil birçok ekranın durumunu etkiler. Durumlara gelince, listenin görüntülenmeye hazır olduğu bir tane var. Küresel BLoC bakış açısından, daha fazla devlet yaratmaya gerek yoktur. Her iki ekran da listeyi görüntülemeli ve belirli ekrana atanmış bireysel BLoC'lar bununla ilgilenmelidir. Küresel BLoC'nin kendisinin uygulanması şöyle görünecektir:
class SocialMediaBloc, Bloc<SocialMediaEvent, SocialMediaState> { nihai SimpleSocialMediaRepository deposu; SocialMediaBloc(this.repository); @geçersiz kıl SocialMediaState get initialState => ListPresented(repository.getSocialMedia); @geçersiz kıl Akış<SocialMediaState> mapEventToState(SocialMediaEvent olayı) zaman uyumsuz* { if (olay CheckboxChecked ise) { verim _mapCheckboxCheckedToState(event); } } SocialMediaState _mapCheckboxCheckedToState(CheckboxChecked olayı) { final updateList = (ListPresented olarak belirtin).list; güncellenmiş liste .firstWhere((item) => item.id == event.itemId) .setFavourite(event.isChecked); ListPresented(updatedList) döndür; } }
İlk durum ListPresented'dir - depodan zaten veri aldığımızı varsayıyoruz. Yalnızca bir olaya yanıt vermemiz gerekiyor – CheckboxChecked . Bu yüzden setFavourite yöntemini kullanarak seçilen öğeyi güncelleyeceğiz ve yeni listeyi ListPresented durumuna sarılmış olarak göndereceğiz.
Şimdi onay kutusuna dokunurken CheckboxChecked olayını göndermemiz gerekiyor. Bunu yapmak için onChanged geri çağrısını ekleyebileceğimiz bir yerde SocialMediaBloc örneğine ihtiyacımız olacak. Bu örneği BlocProvider kullanarak alabiliriz - yukarıda tartışılan modelden Provider'a benziyor. Böyle bir BlocProvider'ın widget ağacında daha yüksekte çalışması için, istenen BLoC nesnesini başlatmanız gerekir. Örneğimizde, ana yöntemde yapılacaktır:
void main() => runApp(BlocProvider( oluştur: (bağlam) { dön SocialMediaBloc(SimpleSocialMediaRepository()); }, alt: ArchitecturesSampleApp()));
Bu sayede ana liste kodunda BlocProvider.of() kullanarak kolayca BLoC'u çağırabilir ve add metodunu kullanarak bir event gönderebiliriz:
class SocialMediaListScreen, StatefulWidget'ı genişletir { _SocialMediaListState createState() => _SocialMediaListState(); } class _SocialMediaListState, State<SocialMediaListScreen> { öğesini genişletir @geçersiz kıl Widget derlemesi(BuildContext bağlamı) { dönüş BlocBuilder<SocialMediaListBloc, SocialMediaListState>( oluşturucu: (bağlam, durum) { if (durum MainListLoaded ise) { ListView'ı döndür( çocuklar: devlet.sosyalMedya .map((item) => CheckboxSocialMediaItem( öğe: öğe, onCheckboxChanged: (isChecked) => BlocProvider.of<SocialMediaBloc>(bağlam) .add(CheckboxChecked(isChecked, item.id)), )) .Listeye(), ); } başka { return Center(child: Text(Strings.emptyList)); } }, ); } }
BLoC'a CheckboxChecked olay yayılımına zaten sahibiz, ayrıca BLoC'un böyle bir olaya nasıl yanıt vereceğini de biliyoruz. Ama aslında… onay kutusu seçiliyken listenin yeniden oluşturulmasına ne sebep olacak? Global BLoC , ekranlara atanan bireysel BLoC nesneleri tarafından işlendiğinden, liste durumlarının değiştirilmesini desteklemez. Çözüm, durumu değiştirmek ve bu duruma göre yanıt vermek için daha önce bahsedilen küresel bir BLoC'yi dinlemektir. Aşağıda, bir onay kutusuyla ana sosyal medya listesine ayrılmış BLoC :

sınıf SocialMediaListBloc Bloc<SocialMediaListEvent, SocialMediaListState> { nihai SocialMediaBloc mainBloc; SocialMediaListBloc({@gerekli this.mainBloc}) { mainBloc.listen((durum) { if (durum ListPresented ise) { add(ScreenStart(durum.list)); } }); } @geçersiz kıl SocialMediaListState get initialState => MainListEmpty(); @geçersiz kıl Akış<SocialMediaListState> mapEventToState( SocialMediaListEvent olayı) zaman uyumsuz* { geçiş (event.runtimeType) { durum ScreenStart: MainListLoaded((event as ScreenStart).list); kırmak; } } }
SocialMediaBloc , ListPresented durumunu döndürdüğünde, SocialMediaListBloc bilgilendirilecektir. ListPresented öğesinin bir liste ilettiğini unutmayın. Öğeyi onay kutusuyla kontrol etme hakkında güncellenmiş bilgileri içerendir.
Benzer şekilde, favoriler sosyal medya ekranına ayrılmış bir BLoC oluşturabiliriz:
class FavouritesListBloc, Bloc<FavouritesListEvent, FavouritesListSate> { nihai SocialMediaBloc mainBloc; FavouritesListBloc({@required this.mainBloc}) { mainBloc.listen((durum) { if (durum ListPresented ise) { add(FavorilerScreenStart(durum.list)); } }); } @geçersiz kıl FavouritesListSate get initialState => FavouritesListEmpty(); @geçersiz kıl Akış<FavouritesListSate> mapEventToState(FavouritesListEvent olayı) zaman uyumsuz* { if (olay FavouritesScreenStart'tır) { var favouritesList = event.list.where((item) => item.isFavourite).toList(); FavouritesListLoaded(favorilerList); } } }
Küresel BLoC'deki durumu değiştirmek, mevcut listeyle FavouritesScreenStart olayının tetiklenmesiyle sonuçlanır. Ardından, favori olarak işaretlenen öğeler filtrelenir ve ekranda böyle bir liste görüntülenir.
Flutter'da birçok alan içeren bir form nasıl oluşturulur
Uzun formlar, özellikle gereksinimler farklı doğrulama değişkenleri veya metin girdikten sonra ekranda bazı değişiklikler varsaydığında zor olabilir. Örnek ekranda birkaç alandan oluşan bir form ve “İLERİ” butonumuz var. Alanlar otomatik olarak doğrulanacak ve form tamamen geçerli olana kadar düğme devre dışı bırakılacaktır. Butona tıkladıktan sonra forma girilen verilerle yeni bir ekran açılacaktır.
Düğme durumunu doğru şekilde ayarlamak için her alanı doğrulamalı ve tüm form düzeltmesini kontrol etmeliyiz. Ardından, toplanan verilerin bir sonraki ekran için saklanması gerekecektir.

Sağlayıcı ile birçok alan içeren bir form nasıl oluşturulur
Uygulamamızda, kişisel bilgi ekranlarına ayrılmış ikinci bir ChangeNotifier'a ihtiyacımız olacak. Bu nedenle, ChangeNotifier nesnelerinin bir listesini sağladığımız MultiProvider'ı kullanabiliriz. MultiProvider'ın tüm torunları tarafından kullanılabilir olacaklar.
class ArchitecturesSampleApp, StatelessWidget'ı genişletir { nihai SimpleSocialMediaRepository deposu; ArchitecturesSampleApp({Anahtar anahtarı, this.repository}) : super(anahtar: anahtar); @geçersiz kıl Widget derlemesi(BuildContext bağlamı) { MultiProvider'ı döndür( sağlayıcılar: [ ChangeNotifierProvider<SocialMediaModel>( create: (bağlam) => SocialMediaModel(depo), ), ChangeNotifierProvider<PersonalDataNotifier>( oluştur: (bağlam) => PersonalDataNotifier(), ) ], çocuk: MaterialApp( başlık: Strings.architecturesSampleApp, debugShowCheckedModeBanner: yanlış, ana sayfa: StartScreen(), yollar: <String, WidgetBuilder>{ Routes.socialMedia: (bağlam) => SocialMediaScreen(), Routes.favourites: (bağlam) => FavouritesScreen(), Routes.personalDataForm: (bağlam) => PersonalDataScreen(), Routes.personalDataInfo: (bağlam) => PersonalDataInfoScreen() }, ), ); } }
Bu durumda PersonalDataNotifier bir iş mantığı katmanı olarak hareket edecek - alanları doğrulayacak, güncellemesi için veri modeline erişime sahip olacak ve görünümün bağlı olacağı alanları güncelleyecektir.
Formun kendisi, özellik doğrulayıcıyı kullanarak doğrulamaları otomatik olarak ekleyebildiğimiz ve onSaved geri çağrısını kullanarak formdaki verileri modele kaydedebildiğimiz, Flutter'ın çok güzel bir API'sidir . Doğrulama kurallarını PersonalDataNotifier'a devredeceğiz ve form doğru olduğunda girilen verileri ona ileteceğiz.
Bu ekrandaki en önemli şey, her alanda bir değişiklik olup olmadığını dinlemek ve doğrulama sonucuna bağlı olarak düğmeyi etkinleştirmek veya devre dışı bırakmak olacaktır. Form nesnesinden onChange geri aramasını kullanacağız. İçinde önce doğrulama durumunu kontrol edeceğiz ve ardından PersonalDataNotifier'a ileteceğiz.
Biçim( anahtar: _formKey, otomatik doğrulama: doğru, onChanged: () => _onFormChanged(personalDataNotifier), çocuk: void _onFormChanged(PersonalDataNotifier personalDataNotifier) { var isValid = _formKey.currentState.validate(); kişiselDataNotifier.onFormChanged(isValid); }
PersonalDataNotifier içerisinde isFormValid değişkeni hazırlayacağız. Bunu değiştireceğiz ( notifyListeners() öğesini çağırmayı unutmayın) ve görünümde, değerine bağlı olarak düğme durumunu değiştireceğiz. Notifier örneğini listen: true parametresiyle almayı unutmayın – aksi takdirde, görünümümüz yeniden oluşturulmaz ve düğme durumu değişmeden kalır.
var personalDataNotifier = Provider.of<PersonalDataNotifier>(bağlam, dinle: true);
Aslında, görünümü yeniden yüklemenin gerekli olmadığı başka yerlerde personalDataNotifier kullandığımız gerçeği göz önüne alındığında, yukarıdaki satır optimal değildir ve listen parametresinin false olarak ayarlanması gerekir. Yeniden yüklemek istediğimiz tek şey düğme, böylece onu klasik bir Tüketici ile sarabiliriz:
Tüketici<PersonalDataNotifier>( oluşturucu: (bağlam, bildirim, çocuk) { dönüş YükseltilmişButton( çocuk: Metin(Strings.addressNext), onPressed: notifier.isFormValid ? /* buton etkinleştirildiğinde yapılacak işlem */ : hükümsüz, renk: Renkler.mavi, devre dışı Renk: Colors.grey, ); }, )
Bu sayede, her bildirimde bulunduğumuzda diğer bileşenleri yeniden yüklemeye zorlamıyoruz.
Kişisel verileri gösteren görünümde artık sorun olmayacak - PersonalDataNotifier'a erişimimiz var ve oradan güncellenmiş modeli indirebiliriz.
BLoC ile birçok alan içeren bir form nasıl oluşturulur?
Önceki ekran için iki BLoC nesnesine ihtiyacımız vardı. Yani başka bir "çift ekran" eklediğimizde, toplamda dört ekranımız olacak. Provider durumunda olduğu gibi, neredeyse aynı şekilde çalışan MultiBlocProvider ile halledebiliriz.
void main() => runApp( MultiBlocProvider(sağlayıcılar: [ Blok Sağlayıcı( create: (bağlam) => SocialMediaBloc(SimpleSocialMediaRepository()), ), Blok Sağlayıcı( create: (bağlam) => SocialMediaListBloc( mainBloc: BlocProvider.of<SocialMediaBloc>(bağlam))), Blok Sağlayıcı( oluştur: (bağlam) => PersonalDataBloc(), ), Blok Sağlayıcı( oluştur: (bağlam) => PersonalDataInfoBloc( mainBloc: BlocProvider.of<PersonalDataBloc>(bağlam)), ) ], alt: ArchitecturesSampleApp()), );
BLoC modelinde olduğu gibi, olası durumlar ve eylemlerle başlamak en iyisidir.
soyut sınıf PersonalDataState {} class NextButtonDisabled PersonalDataState'i genişletir {} class NextButtonEnabled PersonalDataState'i genişletir {} class InputFormCorrect PersonalDataState'i genişletir { nihai PersonalData modeli; InputFormCorrect(bu.model); }
Bu ekranda değişen şey buton durumudur. Bu nedenle, bunun için ayrı devletlere ihtiyacımız var. Ayrıca, InputFormCorrect durumu, formun topladığı verileri göndermemize izin verecektir.
soyut sınıf PersonalDataEvent {} class FormInputChanged PersonalDataEvent'i genişletir { final bool geçerli; FormInputChanged(this.isValid); } class FormCorrect PersonalDataEvent'i genişletir { nihai Kişisel Veri formuVeri; FormCorrect(this.formData); }
Formdaki değişiklikleri dinlemek çok önemlidir, bu nedenle FormInputChanged olayı. Form doğru olduğunda FormCorrect olayı gönderilir.
Doğrulamalar söz konusu olduğunda, Sağlayıcı ile karşılaştırırsanız burada büyük bir fark vardır. Tüm doğrulama mantığını BLoC katmanına dahil etmek istersek, alanların her biri için çok sayıda olayımız olur. Ek olarak, birçok durum, görünümün doğrulama mesajlarını göstermesini gerektirir.
Bu elbette mümkündür, ancak faydalarını kullanmak yerine TextFormField API'sine karşı bir savaş gibi olacaktır. Bu nedenle, net bir neden yoksa, doğrulamaları görünüm katmanında bırakabilirsiniz.
Düğme durumu, BLoC tarafından görünüme gönderilen duruma bağlı olacaktır:
BlocBuilder<PersonalDataBloc, PersonalDataState>( oluşturucu: (bağlam, durum) { dönüş YükseltilmişButton( çocuk: Metin(Strings.addressNext), onPressed: durum NextButtonEnabled ? /* buton etkinleştirildiğinde yapılacak işlem */ : hükümsüz, renk: Renkler.mavi, devre dışı Renk: Colors.grey, ); })
PersonalDataBloc'ta olay işleme ve durumlarla eşleme aşağıdaki gibi olacaktır:
@geçersiz kıl Akış<PersonalDataState> mapEventToState(PersonalDataEvent olayı) zaman uyumsuz* { if (olay FormCorrect ise) { verim InputFormCorrect(event.formData); } else if (olay FormInputChanged ise) { verim mapFormInputChangedToState(olay); } } PersonalDataState mapFormInputChangedToState(FormInputChanged olayı) { if (event.isValid) { NextButtonEnabled() döndür; } başka { NextButtonDisabled() döndür; } }
Kişisel verilerin özetinin bulunduğu ekrana gelince, durum bir önceki örneğe benzer. Bu ekrana eklenen BLoC , form ekranının BLoC'sinden model bilgilerini alacaktır.
sınıf PersonalDataInfoBloc Bloc<PersonalDataInfoEvent, PersonalDataInfoState> { nihai PersonalDataBloc mainBloc; PersonalDataInfoBloc({@required this.mainBloc}) { mainBloc.listen((durum) { if (durum InputFormCorrect'tir) { add(PersonalDataInfoScreenStart(durum.model)); } }); } @geçersiz kıl PersonalDataInfoState get initialState => InfoEmpty(); @geçersiz kıl Akış<PersonalDataInfoState> mapEventToState(PersonalDataInfoEvent olayı) zaman uyumsuz* { if (olay PersonalDataInfoScreenStart'tır) { verim InfoLoaded(event.model); } } }
Flutter mimarisi: hatırlanması gereken notlar
Yukarıdaki örnekler, iki mimari arasında açık farklar olduğunu göstermek için yeterlidir. BLoC , görünüm katmanını iş mantığından çok iyi ayırır. Bu, daha iyi yeniden kullanılabilirlik ve test edilebilirlik gerektirir. Basit durumları ele almak için Provider'dan daha fazla kod yazmanız gerekiyor gibi görünüyor. Bildiğiniz gibi bu durumda uygulamanın karmaşıklığı arttıkça bu Flutter mimarisi daha kullanışlı hale gelecektir.
İşletmeniz için geleceğe yönelik bir uygulama oluşturmak ister misiniz?
iletişime geçelimSağlayıcı ayrıca UI'yi mantıktan iyi bir şekilde ayırır ve her kullanıcı etkileşimi ile ayrı durumların oluşturulmasını zorlamaz; bu, basit bir durumu ele almak için genellikle büyük miktarda kod yazmanız gerekmediği anlamına gelir. Ancak bu daha karmaşık durumlarda sorunlara neden olabilir.
Tüm projeyi incelemek için buraya tıklayın.