folder Tahribat.com Forumları
linefolder Mobil Programlama
linefolder State Management In Flutter



State Management In Flutter

  1. KısayolKısayol reportŞikayet pmÖzel Mesaj
    unbalanced
    unbalanced's avatar
    Kayıt Tarihi: 14/Haziran/2006
    Erkek

    Selamlar

    Yarin proje yöneticisiyle bir görüsmem olacak. State Management paketlerini karsilastiracagim. Önümüzdeki secenekler BLoC, Cubit, MobX ve GetX.

    Bunlarin avantajlari ve dezavantaklarini yazmam gerekiyor. Arastiriyorum bir yandan.

    Aranizda flutter'da state management kullananlar varsa:

    hangi paketi neden kullaniyorlar, ne eksiklerini görüyorlar ve diger paketleri kullanmama sebepleri nelerdir?

    Herkes kendi fikrini yazarsa güzel bir bilgi paylasimi olur. Sonraki mesajda ben de yazacagim


    Ülkesini Seven Her Türk Vatandasi, Ülkesinin Sessiz Istilasi'na karsi durmak zorunda.
  2. KısayolKısayol reportŞikayet pmÖzel Mesaj
    unbalanced
    unbalanced's avatar
    Kayıt Tarihi: 14/Haziran/2006
    Erkek

    Ben projelerimde MobX kullaniyorum. Cünkü cok kolay bir yapisi var. setState, notifyListeners gibi metodlar cagirmama gerek yok.

    ViewModel icinde; degiskenim icin @observable attribute'unu, degiskeni degistirecek metodu da @action attributunu kullaniyorum. List yerine ObservableList kullaniyorum bu kadar.  Daha sonra UI tarafinda agac yapisina göre Observer ile sarmaliyorum bittiyor.

    BLoC yapisini cok karisik buluyorum, cok fazla boilerplate var.. O yüzden zaten Cubit'i cikardilar. Daha mantikli geldi bana.

    Biraz GetX'i inceleme sansim oldu. Adamlar 10 tane ayri paketi bir pakete sigdirmislar. GetX'e state management harici, kendi navigator'u, snackbar'i, http requester'i, dependency injection'i, tema degistirici özelligi gibi özellikleri var. Bir yazilimci olarak, all in one paketlere pek sicak bakmiyorum. Cünkü maintain etmesi zor, bir hata ciktiginda ve core'u etkilediginde büyük sikinti olur. O olmasa bile yazilimcilarinin hatayi düzeltmesi zaman alir.

    Tabi duruma göre  bir cok paketin olmasi avantaj da sayilabilir cünkü kolay sekilde bir cok isinizi yapabiliyorsunuz ancak profesyonel olarak mantikli bulmadim. Bir de context almadan bu isleri yapiyor, anladigim kadariyla baslangicta bir tane custom material app olusturuyorsunuz, ordaki contex'i kullaniyor.

    Surada cok iyi bir elestiri yazisi var, icinde cok paket oldugunu ögrendikten sonra bu yaziyi yazan kisiyle ayni seyi düsünmüsüm. Aklin yolu bir demek ki :)

    GetX ve MobX'de unit test yazmak cok kolay degil. BLoC ve cubit icin test paketi de olusturmuslar, unit testler kolayca yapilabiliyor  https://pub.dev/packages/bloc_test

    Kendi sahsi projelerimde Mobx + Provider kullanacagim. Is hayatinda tercih benim elimde olursa Cubit + Provider kullanacagim. GetX'i iyi bilseydim, hizli gelistirilmesi gereken en azindan smoke testler ya da proof of concept icin getX iyi görünüyor. Ama bir projemde kullanmayi asla düsünmüyorum.

     


    Ülkesini Seven Her Türk Vatandasi, Ülkesinin Sessiz Istilasi'na karsi durmak zorunda.
  3. KısayolKısayol reportŞikayet pmÖzel Mesaj
    makets
    makets's avatar
    Kayıt Tarihi: 17/Ocak/2010
    Erkek

    hepsi aynı şeyin laciverti hocam. Projenin sürdürülebilirligi için provider, flutter_bloc paketlerini önerebilirsin çünkü kullanıcısı çok. Yarın bir gün projeye yeni yazılımcı arkadaş dahil olduğunda bu paketleri biliyor olma ihtimali yüksek ama örneğin sıklıkla tercih ettiğim stacked paketini ya da redux, riverpod paketini kullanan az. Tüm bunları kullanmayıp stream ile bir kütüphane yazıp onu da tercih edebilirsin. Fakat o kütüphaneyi başka yazılımcıya kullandırabilmek maliyetli.

  4. KısayolKısayol reportŞikayet pmÖzel Mesaj
    unbalanced
    unbalanced's avatar
    Kayıt Tarihi: 14/Haziran/2006
    Erkek
    makets bunu yazdı

    hepsi aynı şeyin laciverti hocam. Projenin sürdürülebilirligi için provider, flutter_bloc paketlerini önerebilirsin çünkü kullanıcısı çok. Yarın bir gün projeye yeni yazılımcı arkadaş dahil olduğunda bu paketleri biliyor olma ihtimali yüksek ama örneğin sıklıkla tercih ettiğim stacked paketini ya da redux, riverpod paketini kullanan az. Tüm bunları kullanmayıp stream ile bir kütüphane yazıp onu da tercih edebilirsin. Fakat o kütüphaneyi başka yazılımcıya kullandırabilmek maliyetli.

    öyle hocam, arkaplanda aslinda bizim yapmamiz gerekenleri kendileri yapmislar. Demo uygulamasini streamler ve bloc kullanarak yapmislar, acayip bir sürü kod var. Ben mobx ile yaptim cok kisa sürede bitirdim. Isi kolaylastirmak varken cok ugrasmaya gereken yok, bir de kapsamli bir projeyse.. Bloc'un dezavantaji dedigim gibi boilerplate kodlari cok fazla. Kontrol saglamak güzel ama bir noktadan sonra yorucu. O yüzden Cubit bana daha mantikli geliyor. Zaten hem bloc hem cubit ayni yerden geliyor.

    Sanirim sitede flutter ile calisan yok ya da state managment kullanan pek yok


    Ülkesini Seven Her Türk Vatandasi, Ülkesinin Sessiz Istilasi'na karsi durmak zorunda.
  5. KısayolKısayol reportŞikayet pmÖzel Mesaj
    MhmdAlmz
    MhmdAlmz's avatar
    Kayıt Tarihi: 09/Ağustos/2015
    Erkek

    Ben her zaman esnek olmayı seviyorum. Bundan dolayı tek bir mimari üstüne kendi prensiplerimi uyguluyorum. Bunu yapan tanıdığım bir çok sağlam adam var gerek backendci gerek frontendci.

    Backend bile yazdığınızda MVC mimarisinin üzerine herkes kendi kurallarını kendi yapısını entegre ediyor. Kimi middleware yazıyor bazı çözümler için kimisi helper sınıf yada base class. Bu da senin söylediğin gibi hocam bir çok değişik boilerplate çıkarıyor ortaya. 

    Yazılımcı arkadaşlar belki bana kızacak ama benim şöyle bir görüşüm var. Kütüphaneleri yığıyorlar projeye projeyi eklediği kütüphaneler yazmış gibi oluyor daha sonra Dependency Injection sınıfı ile eklediği kütüphanelerle uğraşıyor. Arkadaş ne gerek var. Senin aslında adamın yazdığı 10 satırlık koda ihtiyacın var senin. Tüm kütüphaneye değil ki. Gir ilgili kütüphanenin belirli kısmını al projene göm. Hem çalışma mantığını öğrenirsin hemde kendine göre uyarlarsın. 

    Bundan dolayı ben düz RxDart ile Observable pattern kullanarak Bloc mimarisini kullanıyorum projelerimde. Üstüne senin dediğin gibi kendi yapımı entegre ettim. Evet piyasadan farklı ya da öğrenmesi biraz daha zor. Ama kodu açıklayan readme.md dosyası ve kod içine açıklamalar yazdıktan sonra anlamayanın da o projede işi yok. 

    https://github.com/neyasis-technology/Neyasis_Flutter_Boilerplate bu linkteki boilerplate inceleyebilirsin hocam. Bu boilerplate ile 13 proje yazdık ben herhangi bir sıkıntısını görmedim. Boilerplate de CI/CD Süreçlerini kolaylaştıran bir takım özelliklerde var. 

    Gelelim bu boilerplate de ya da kendi projelerimde neden MobX, GetX, GetIt, Riverpod, Redux, Fish redux veya Binder kütüphanelerini kullanmıyorum. Bu kütüphanelerin hep bir sıkıntısı oluyor bir de istediğim bir geliştirme için issue açmak zorunda kalıyorum. Ya da paket değişikliliğine gidiyorum. Bunun böyle olması beni tahrik ediyor. Daha önce GetX kullandım senin de dediğin gibi çok fazla yardımcı kütüphane var içinde ama ben sadece statemanagement için kullanmak istiyorum ama maalesef diğer paketleri de kullanmak durumunda kalıyorum. Belki ben GetX içerisindeki Multilang  kütüphanesini değil de native tarafta ekranlarım var diyelim ve native tarafa da destek veren bir multilang kütüphanesi kullanmak istiyorum. Bu durumda projemde 2 tane multilang kütüphanesi olmuş oluyor. Çakışma ihtimali çok yüksek :P 

    Bunun yanı sıra ekran geçişlerini ben animasyonlu yapıyorum. Bu kütüphane yüzünden animasyonlu geçişler yapamıyorum Flutter'ın default geçişleri kalıyor. gibi gibi gibi...

    Şimdi neden Bloc mimarisini kullandığıma geleyim.

    Öncelikle WidgetTest, Integration Test ve Automation test yazıyoruz.  WidgetTest yazarken örneğin login buttonuna tıkladık. Button tıklama işlemlerinde Animasyon/API Call olduğu zaman maalesef test işlemlerimiz başarılı gerçekleşmiyor. WidgetTest yazarken API çağıramıyoruz genellikle MOCK API kullanarak ilerliyor bir çok insan. Ama ben api sonuçlarına göre Widget çizdiğim için API çağrısı yapmak durumunda kaldım. Burda da Bloc kullandığım için çoook şanslıydım :P

     

    Şöyle bir kod yazdım. (Bu kodu normal flutter'in StreamMacher sınıfına girerek okuyup kendim için biraz değiştirdim.)

      static StreamMatcher streamMatcher({required TestHelperResults Function() statement}) {
        return StreamMatcher((queue) async {
          bool hasError = false;
          Future tryHere() => queue.withTransaction((stream) async {
                await stream.next;
                TestHelperResults result = statement();
                if (result == TestHelperResults.failed) {
                  hasError = true;
                } else if (result == TestHelperResults.success) {
                  return true;
                }
                return false;
              });
          while (await queue.hasNext) {
            if (await tryHere()) return null;
            if (!hasError) {
              await queue.next;
            } else {
              break;
            }
          }
          print("Test sonsuz döngüye girdi");
        }, 'Custom Stream Matcher');
      }

    Bu da login success kod örneğim.

    Future loginWithOtpSuccess(WidgetTester widgetTester) async {
      createOtpBloc.setWidgetTester(widgetTester);
      loginWithOtpBloc.setWidgetTester(widgetTester);
      final mockObserver = MockNavigatorObserver();
      await TesterHelper.initializeTestWidget(widgetTester: widgetTester, mockObservable: mockObserver);
      await widgetTester.pumpAndSettle(Duration(seconds: 3));
      mockObserver.didPush(MaterialPageRoute(builder: (_) => LoginScreen()), MaterialPageRoute(builder: (_) => SplashScreen()));
      final phoneText = find.byKey(Key("phoneNumberInput"));
      final loginButton = find.byKey(Key("loginButton"));
      expect(phoneText, findsWidgets);
      await widgetTester.enterText(phoneText.last, LoginTestMocks.successPhone);
      await widgetTester.tap(loginButton.last);
      await expectLater(
        createOtpBloc.fetcher.stream,
        TesterHelper.streamMatcher(
          statement: () {
            if (createOtpBloc.store != null) return TestHelperResults.success;
            if (createOtpBloc.httpError != null) {
              throw (createOtpBloc.httpError!.errorMessage);
            }
            return TestHelperResults.next;
          },
        ),
      );
    
      mockObserver.didPush(MaterialPageRoute(builder: (_) => OtpScreen()), MaterialPageRoute(builder: (_) => LoginScreen()));
    
      await widgetTester.pumpAndSettle(Duration(seconds: 2));
    
      final otpCodeInput = find.byKey(Key("otpCodeInput"));
      expect(otpCodeInput, findsWidgets);
      final verifyOtpCodeButton = find.byKey(Key("verifyOtpCodeButton"));
      expect(verifyOtpCodeButton, findsWidgets);
      await widgetTester.enterText(otpCodeInput.last, LoginTestMocks.otpCode);
      await widgetTester.tap(verifyOtpCodeButton.last);
    
      await expectLater(
        loginWithOtpBloc.fetcher.stream,
        TesterHelper.streamMatcher(
          statement: () {
            if (loginWithOtpBloc.store != null) return TestHelperResults.success;
            if (loginWithOtpBloc.httpError != null) throw ("Login başarısız");
            return TestHelperResults.next;
          },
        ),
      );
    }

    Buda OTP hatalı senaryo.

    Future loginWithOtpError(WidgetTester widgetTester) async {
      createOtpBloc.setWidgetTester(widgetTester);
      loginWithOtpBloc.setWidgetTester(widgetTester);
      final mockObserver = MockNavigatorObserver();
      await TesterHelper.initializeTestWidget(widgetTester: widgetTester, mockObservable: mockObserver);
      await widgetTester.pumpAndSettle(Duration(seconds: 5));
      mockObserver.didPush(MaterialPageRoute(builder: (_) => LoginScreen()), MaterialPageRoute(builder: (_) => SplashScreen()));
      final phoneText = find.byKey(Key("phoneNumberInput"));
      final loginButton = find.byKey(Key("loginButton"));
      await widgetTester.enterText(phoneText.last, LoginTestMocks.errorPhone);
      await widgetTester.tap(loginButton.last);
      await expectLater(
        createOtpBloc.fetcher.stream,
        TesterHelper.streamMatcher(
          statement: () {
            if (createOtpBloc.store != null) throw ("Hatalı test işleminde. Login işlemi başarıyla gerçekleştirildi.");
            if (createOtpBloc.httpError != null) {
              return TestHelperResults.success;
            }
            return TestHelperResults.next;
          },
        ),
      );
    }
    

    Şimdi bunu yapabildim ama GetX, flutter_bloc, Redux gibi yapılar kullansaydım hayatta yapamazdım. Gidip github issue açacağım da adamlar gelecek cevap verecek te falan filan. Uzun iş 2-3 günlük araştırma ile 10 satırlık kod yazdım. Bundan dolayı benim görüşüm Bloc mimarisi üstüne kendi yapınızı şirket kültürünüzü entegre etmeniz abi. Şirkete alınan herkes zaten 1-2 ay şirket kültürünü öğrenmek için çalışıyor ondan sonra tam anlamıyla oturup kod yazıyor. Senin kodların spagetti olmuyor ki gidip Cubit kullanasın. Niye adamların kurallarına uyuyorsun ki. Burda kütüphaneye bağlı olmak kötü. Bence kodları ortak bir yapıya getirmek için mimariler yeterli. 

    Bir projede X mimariyi kullanman ve o X mimariyi bilen kişiyi işe alman projenin sürdürülebilirliği açısından yeterli olduğunu düşünüyorum. Kullanma GetX Felan. 

    Sana GetX ile ilgili bir şeyler anlatayım :D

    GetX geliştiren vatandaş çok da iyi bir vatandaş değil. Projeye çok önem göstermiyor vs vs. 

    https://github.com/flutter/website/commit/3f5c42f438b317ec412b79a9d90f52edb602f54f bu commiti atan kişi Flutterin dart takımının geliştiricisi adamın commit mesajını oku :D

    https://www.reddit.com/r/FlutterDev/comments/hmjff1/people_who_are_you_using_getx_how_do_you_feel/fx7hwp7/ bir reddit konusu okuyun insanlar neler düşünüyorlar.

    Adam kod çalıyor ama referans göstermiyor https://github.com/jonataslaw/getx/issues/509 

    Bence kendi yapınızı yazın kimsenin yapısını entegre etmeyin projelerinize. O adamlar bizden zeki değiller. 

    Aklıma bir örnek geliyor. React-Native yazdığım zamanlarda Redux-Thunk kullanıyorduk Statemanagement middleware için. Bayağı da iyi bir kütüphanedir kendileri. Fanı da çoktur. Hatta Redux-Saga dan iyi olduğunu söylerler.

    Github da 16.7k yıldızı vardır :D :D :D Peki bu kod ne işe yarar ? https://github.com/reduxjs/redux-thunk/blob/master/src/index.ts Aha sana 30 satırlık kod :D :D 16.7k :D Peki neden? İnsanlar bağımlı olmayı seviyor üşeniyorlar.

    Elbette amerikayı yeniden keşfetmeye gerek yok. Ama dünya haritası icat edildiği zaman bırakın da nerede yaşayacağımızı biz seçelim değil mi ? :D

     

    Yanlış hatırlamıyorsam daha önceden Cubit ile https://pub.dev/packages/flutter_screenutil bu paketi kullanamıyordun abi. Bu paket UI/UX için muhteşem'ül ala bir paket :D Çok severim kendilerini :) Zeplin/Sketch vb. yerden sana tasarım geldiğinde tasarımcı hangi telefonu baz aldıysa sende o telefonun yükseklik genişliklerini veriyorsun. Bu şanlı paket her şeyi kendisi ayarlıyor. Fontsize, width, height vb.

    EDİT;

    Son olarak, hereksin yoğurt yiyişi farklıdır. Projeden projeye state management değişkenlik gösterebilir. MobX de fazla kod yazmıyorsun ama redux_bloc kütüphanesinde mesela çok kod yazıyorsun, Bloc tanımla state tanımla model tanımla vs. vs. 

     

    Mimari karşılaştırmasında daha önce Content Provider (Eski ismi ile MVVM) kullanıyordum ama Bloc daha iyi geldi bana. Fikrimi de bu makaleyi okuduktan sonra  değiştirdim https://www.miquido.com/blog/flutter-architecture-provider-vs-bloc/

    MhmdAlmz tarafından 29/Eki/21 11:55 tarihinde düzenlenmiştir

    Andolsun kuşluk vaktine ve dindiği zaman o geceye ki, Rabbin sana veda etmedi ve darılmadı! Ve kesinlikle senin için sonu önünden (ahiret dünyadan) daha hayırlıdır. ileride Rabbin sana verecek de hoşnut olacaksın! O, seni bir yetim iken barındırmadı mı? Seni, yol bilmez iken (doğru) yola koymadı mı? Seni bir yoksul iken zengin etmedi mi? Öyle ise, sakın yetime kahretme (onu horlama)! El açıp isteyeni de azarlama! Fakat Rabbinin nimetini anlat da anlat!
  6. KısayolKısayol reportŞikayet pmÖzel Mesaj
    unbalanced
    unbalanced's avatar
    Kayıt Tarihi: 14/Haziran/2006
    Erkek

    destanin icin tesekkürler hocam, senden bekledigim gibi, emegine saglik :) simdi okuyup notlar cikarayim. Inceledikten sonra yorumumu yazarim. Tesekkürler tekrar

    ikinci mesajdaki link bozulmus => https://medium.com/@darwinmorocho/flutter-should-i-use-getx-832e0f3a00e8

    unbalanced tarafından 29/Eki/21 12:47 tarihinde düzenlenmiştir

    Ülkesini Seven Her Türk Vatandasi, Ülkesinin Sessiz Istilasi'na karsi durmak zorunda.
  7. KısayolKısayol reportŞikayet pmÖzel Mesaj
    MhmdAlmz
    MhmdAlmz's avatar
    Kayıt Tarihi: 09/Ağustos/2015
    Erkek
    unbalanced bunu yazdı

    destanin icin tesekkürler hocam, senden bekledigim gibi, emegine saglik :) simdi okuyup notlar cikarayim. Inceledikten sonra yorumumu yazarim. Tesekkürler tekrar

    ikinci mesajdaki link bozulmus => https://medium.com/@darwinmorocho/flutter-should-i-use-getx-832e0f3a00e8

    Rica ederim keyifli okumalar :) 


    Andolsun kuşluk vaktine ve dindiği zaman o geceye ki, Rabbin sana veda etmedi ve darılmadı! Ve kesinlikle senin için sonu önünden (ahiret dünyadan) daha hayırlıdır. ileride Rabbin sana verecek de hoşnut olacaksın! O, seni bir yetim iken barındırmadı mı? Seni, yol bilmez iken (doğru) yola koymadı mı? Seni bir yoksul iken zengin etmedi mi? Öyle ise, sakın yetime kahretme (onu horlama)! El açıp isteyeni de azarlama! Fakat Rabbinin nimetini anlat da anlat!
Toplam Hit: 2683 Toplam Mesaj: 7
flutter state management flutter