Flutter öğrenmeye, öğrendikçe yazmaya çalışıyorum. Bu birazda tetikleyici rol alıyor benim için. Bu aşamada yazdıklarımda hatalar olabilir, iletirseniz tabiki hatalarımı düzeltirim.
Flutter da State management dendiğinde ilk başlarda zihnimde bir şeyler canlanmıyordu, biraz biraz şekillenmeye başladı. Widget lar,sınıflar,sayfalar arası verilerin alınması, verilmesi bir yerde bekletilmesi olarak düşünebiliriz.
Sizlerin daha iyi bildiği gibi, bir ağaca benzeyen yapısı ile verileri taşımak biraz güç. En yukarıdaki sınıfın içinde bulunan widget dan, yapının en altındaki widget e veri almak biraz zahmetli ve sistem için pahalı. Bu yüzden bazı paketler geliştirilmiş provider paketi bunlardan biri.
Paketinin çalışmasına bakarsak, işlenecek veriler hiyerarşik yapının dışında tutuluyor diyebiliriz. Bir nevi bir data sınıfı oluşturuyoruz ve alacağımız vereceğimiz bilgileri buraya gönderiyor, sonrada “veri değişti” diyerek yayın yapıyoruz. Sonrasında ilgili widget lar gerekeni yapıyor. Yapısını çok basit bir çizimle aşağıda şekilde görebilirsiniz. Ayrıca flutterda “tekrar boyama” yapılması için statefull widget kullanılması gerekirken, provider ile bu ortadan kalkıyor. Stateless widgetda da, artık tekrar boyamak veriyi değiştirmek provider ile mümkün.
Şimdi, provider paketini projeye yüklemek için iki yol var.
- Flutter projesinin klasörü içerisinde terminale flutter pub add provider yazarak, ki bu pubspec.yml dosyası içinde değişiklikleri otomatik yapıyor.
- pubspec.yml dosyası içerisinde aşağıdaki değişikliği yapmak.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 provider: ^5.0.0 dev_dependencies: flutter_test: sdk: flutter |
Bu hazırlığı yaptıktan sonra yapılması gereken bir “veri model sınıfı” oluşturmak. Alınacak gönderilecek verileri buradan yollayacağız ya da alacağız, üzerinde işlem yapacağız
Veri model sınıfına models.dart adını verdim. Bu dosya içerisinde üç sınıf oluşturdum. Dosya içeriği aşağıda. Sınıfların içindeki notifyListeners() metodları “dinleyicilere” veri değişti bilgisi vermek için kullanılıyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import 'package:flutter/material.dart'; class IntegerModel with ChangeNotifier{ int counter=0; int readCounter(){ return counter; } void incCounter(){ counter++; notifyListeners();//değişiklik yapıldı bilgisi yapılıyor PyQt deki signal gibi. } void decCounter(){ counter--; notifyListeners();//değişiklik yapıldı yayını yapılıyor. PyQt deki signal gibi. } } class IntegerModelWithParam with ChangeNotifier{ int counter=0; int readCounter(){ return counter; } void incCounter(int incVal){ counter=counter+incVal; notifyListeners();//değişiklik yapıldı bilgisi yapılıyor PyQt deki signal gibi. } void decCounter(int decVal){ counter=counter-decVal; notifyListeners();//değişiklik yapıldı yayını yapılıyor. PyQt deki signal gibi. } } class StringModel with ChangeNotifier{ String _message="Yakarsa Dünyayı Garipler Yakar"; String readMessage(){ return _message; } void writeMessage(String message){ _message=message; notifyListeners();//mesajın değiştiği bilgisi verildi. } } |
Daha sonra bu verilere erişecek uygulama sınıflarını oluşturmak gerekiyor. Bunlar ise page2,page3,page4 adlı dosyalarda barıdırdım. Bu sınıflar içindeki widgetlerin sarıldığı (wrapping) Consumer i açıklamak için kod örneğinden yararlanmakta yarar var.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:provider_state_man_app/models.dart'; class SecondPageClass extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("İkinci Sayfa"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Consumer<IntegerModel>( builder: (context, IntegerModelObject, child) { return Text( "${IntegerModelObject.readCounter()}", style: TextStyle(fontSize: 36), ); }, ), Consumer<IntegerModel>( builder: (context, IntegerModelObject, child) { return ElevatedButton( child: Text("Sayaç Arttır"), onPressed: () { IntegerModelObject.incCounter(); }, ); }, ), Consumer<IntegerModel>( builder: (context, IntegerModelObject, child) { return ElevatedButton( child: Text("Sayaç Azalt"), onPressed: () { IntegerModelObject.decCounter(); }, ); }, ), ], ), ), ); } } |
Yukarıdaki kod örneğinde IntegerModel: verinin gönderileceği sınıf ve IntegerModelObject:ModelSınıfını temsil eden obje olarak tanımlayabiliriz. Dikkat ederseniz OnPressed() metodunda models.dart dosyası içerisindeki, IntegerModel sınıfı içindeki incCounter metodu çalıştırılmıştır.
Bu işlemleri yaptıktan sonra verinin taşınacağı, işleneceği alınacağı yere provider işlemlerini yapmak kaldı. Ben bunu en üstte bulunan sınıf içerisinde yaptım. main.dart dosyası içerisinde materialApp widget ini MultiProvider ile sardıktan ve child olarak materialApp ı gösteriyoruz. Şimdi ChangeNotifierProvider ları oluşturma zamanı. Örnek çalışmada üç adet ChangeNotifierProvider tanımladım. Bir örneği aşağıda.
1 2 3 4 5 6 7 8 9 |
Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => IntegerModel()), //madels içerisindeki sınıflara ulaşıyoruz. ChangeNotifierProvider(create: (context) => IntegerModelWithParam()), ChangeNotifierProvider(create: (context) => StringModel()), ], child: MaterialApp( |
buradaki IntegerModel(), models.dart dosyası içerisindeki bir sınıf. Verilere ulaşacak olan widget ler buradan veri alacak. Tabi “değişiklik oldu” haberi geldikten sonra.
Şimdi Bu widget lara yapılacak işlemleri hazırlayalım. Bu işlemi yine Consumer widget i ile yapacağız. Main.dart içerisinde bulunan Text widget ine, models.dart içerisindeki integerModel sınıfındaki readCounter metoduyla veri alıyoruz aşağıdaki örnekte.
1 2 3 4 5 6 7 8 |
Consumer<IntegerModel>( builder: (context, integerModelObject, child) { return Text( "Sayfa2 den gelen veri:${integerModelObject.readCounter()}", style: TextStyle(fontSize: 20), ); }, ), |
Çalışmanın dosyaları için tıklayınız.
Sağlıcakla.