Proje Altyapı Kurulumları
Farklı Flutter SDK versiyonları kullandığımız uygulamalarımızı Flutter Version Manager (FVM) ile yönetebiliriz.
FVM kurulumu:
- flutter pub global activate fvm
- .zshrc dosyasına PATH ortam değişkenlerini ekle.
- export PATH=”$PATH”:”$HOME/.pub-cache/bin”
- export PATH=”$PATH”:”$HOME/.fvm”
- pubspec.yaml içindeki environment: sdk : değeri projede kullanılan dart versiyonunu gösterir. Bununla uyumlu flutter SDK versiyonu kullanılmalıdır.Örneğin 3.3.1 flutter versiyonu 2.18.0 dart versiyonu ile uyumludur. Flutter SDK archive sayfasını incele.
- Bir projede flutterb3.3.1 iken diğerinde 3.10.5 olabilir.
- fvm install 3.3.1 diyerek versiyonu yükle.
- fvm use 3.3.1 diyerek projenin kullanacağı versiyonu belirliyoruz.
- fvm install ve use işleminden sonra projeler arasında geçiş yapıp flutter –version dediğimizde farklı SDK’ları işaret ettiklerini görürüz. Yine visual studio code içinde command + shift + P dedikten sonra flutter: change SDK diyerek SDK değişim işlemini gerçekleştiririz.
- ilk fvm kurulumu yapıldığında /Users/<username>/ altında bir fvm klasörü otomatik olarak oluşur ve versiyonlar bu klasör altında tutulur.
- /Users/<username>/Library/Application Support/Code/User/settings.json dosyası içinde versiyonlar listelenir.
"dart.flutterSdkPaths": [
"/Users/<username>/fvm/versions/2.10.5",
"/Users/<username>/fvm/versions/3.3.1",
"/Users/<username>/fvm/versions/3.10.5"
]
visual studio code içinde change SDK dediğimizde bu dosyaya eklenen satırlar görüntülenir.
Change SDK neden önemli? Çünkü projenin içindeki bağımlılıkları flutter clean ve flutter pub get ile yüklemeye çalıştığımızda ilgili bağımlılıkların kullanılan SDK içindeki karşılıklarını getirir.
Flutter Projesini IOS Simülatörde Çalıştırmak
- Projeyi indir. Proje içinde ios ve macos klasörleri olacak.
- Xcode’a git ve yeni bir simülatör oluştur. (Windows altında devices and simulators)
- Proje içindeki ios klasörü altındaki Runner.xcworkspace’i Xcode içinde proje olarak aç.
- Ios klasörü içinde Podfile dosyasındaki platform versiyon değerini öğren. Comment satırı da olsa o değer Xcode içindeki Deployment target değeriyle eşleşmeli.
- Visual studio code içinde Android / IOS Simülatör adlı bir extension var. ISO simülatör bu extension üzerinden çalıştırılır.
- Xcode içindeki projeye git. Runner’a tıkla. Sağdaki alanda PROJECT ve TARGETS kısımları var.
- PROJECT içindeki Runner’a tıkla. Info sekmesine git. Orada IOS Deployment Target kısmını PodFile içindeki değerle eşleştir.
- TARGETS kısmındaki Runner’a tıkla. General sekmesinde Minimum Deployments değerini PodFile içindeki değerle eşleştir.
- Kaydet ve işlemin tamamlanmasını bekle.
- Visual Studio Code terminale gel. flutter clean komutunu çalıştır.
- ios klasörü altındaki Pods klasörünü ve Podfile.lock dosyasını sil.
- flutter pub get
- terminalde ios klasörü içine git. pod install komutunu çalıştır.
- Proje klasörüne dön. Fltter: select device -> IOS simulatör seç. run without debugging.
1- Stateful widget değişebilen(mutable) bir durumda. Yok edilmediği sürece durumunu defalarca değiştirebilir.
Dispose: Stateful widget tarafından oluşturulan state objesi yok edildiğinde çağrılır.
2- TextFormField içine gireceğimiz bir text ya da number değerine padding eklemek için (kutucuk içindeki yazının alt, üst ve yandan boşluk alanı içermesi) InputDecoration içine contentPadding eklemesi yapılır. contentPadding: EdgeInsets.symmetric(vertical: 5, horizontal: 5) .
3- Dart ile bugünün tarihini almak için DateTime bugun = DateTime.now(); — tarihi zaman bilgisi olmadan alıp String olarak gönderebilmek için String bugunWOtime = “${bugun.year}-${bugun.month}-${bugun.day}”;
4- TextFormField içine girilen değeri alabilmek için
controller: _trenNoController,
Controller tanımı için state içinde
final _trenNoController = TextEditingController();
Bir method içinde parametre olarak gönderirken _trenNoController.text .
5- Elimizde tekrarlayan(duplicate) değerler içeren bir liste olsun. Tekrarlayan değerleri kaldırmak için toSet() methodunu kullan. Set, tekrarlayan eleman içermeyen bir collection yapısıdır. Duplicate değerlerin olmadığı bu Set’i tekrar listeye döndürmek için toList() methodunu kullan. (bolgeList! .toSet() .toList();)
6- Bir String içinde number ve character değerleri bir arada bulunuyorsa ve bizim ihtiyacımız olan sadece number değerler ise, regular expression kullanarak number olmayan değerleri kaldırırız.
String myValue = “234r3s67p”;
String myNewValue = input.replaceAll(RegExp(r'[^0-9]’), ”);
(Yeni değer : 234367)
7- Bir sayfada cihazın back butonunu kullanarak geri dönüşleri engellemek için bütün içeriğin tutulduğu widget WillPopScope ile wrap edilmesi lazım.
WillPopScope( onWillPop: () async { return false; }, child: MaterialApp( …..
Burada önemli olan ilgili sayfaya yönlendirme işlemini Navigator.pushReplacementNamed ile yapmaktır.
8- State ifadesi data(veri) olarak düşünülebilir. StatefulWidget ise bir sayfa işlenirken veri değişimi durumu söz konusu ise kullanılması gereken widgettır. StatelessWidget ise sayfada veri değişimi olmadığı durumda kullanılacak widgettır. Bu veri değişimi bir butona tıklandıkça sayfada görünen resmin değişimi gibi düşünülebilir.
9 – list, set ya da map elemanlarının her birine iterable arayüzü ile erişilerek üzerlerinde işlem yapılabilir.
Iterable<int> intList= [1,2,3];
for (final deger in intList) {
print(deger);
}
first ve last özellikleri
print(‘ilk eleman is ${intList.first}’);
print(‘Son eleman is ${intList.last}’);
firstWhere()
intList.firstWhere((deger) => deger > 5);
any(), every()
intList.any((deger) => deger>5) -> boolean en az bir deger eşleşti mi
items.every((deger) => deger >= 5) -> boolean bütün değerler eşleşti mi
where() -> Şartları karşılayan tüm elemanlar
takeWhile() -> belirtilen değere kadar olan değerleri al
skipWhile() -> belirtilen değer ve sonrasındaki değerleri al
map() -> collection içindeki tüm elemanlara yeniden bir değer ataması yapabilir.
Komut satırından Flutter projesi oluşturma
Bilgisayarımızda flutter ve dart kurulumunu tamamladıktan sonra
flutter –version ve dart –version komutlarını çalıştırarak kurulu sürümleri görelim.
Projemizi oluşturacağımız klasörü oluşturduktan sonra terminalde bu klasöre gidelim ve aşağıdaki komutu çalıtıralım.
flutter create ‘uygulamanizin_adi’
Flutter projesini gitlab’e ekleme
Flutter projesi oluşturma yazısını incele.
Gitlab üzerinde aynı isimli yeni bir proje oluştur. Clone sekmesinden Clone with HTTP linkini kopyala. Terminalden projenin klasörüne git. Aşağıdaki komutları çalıştır.
git init
git add .
git remote add origin <kopyaladiginURL>
git commit -m “Initial Commit”
git push -u origin master
Tag eklemek istersen;
git add tag “step-1”
git push tags
Flutter SOAP Web service bağlantısında basic authorization işlemi
response headerının içine aşağıdaki basicAuth stringi “authorization”: basicAuth şeklinde verilir.
String username = ‘usrname’;
String password = ‘psswrd’;
String basicAuth =’Basic ${base64Encode(utf8.encode(‘$username:$password’))}’;
Flutter NFC Manager Kütüphanesi
https://pub.dev/packages/nfc_manager
adresinden nfc_manager kütüphanesini görüntüleyebiliriz.
Terminalde aşağıdaki kodu çalıştırırız;
flutter pub add nfc_manager
pubspec.yaml içine aşağıdaki dependecy’leri ekleyelim.
dependencies:
nfc_manager: ^3.2.0
AndroidManifest.xml dosyasının içine (app/src/main) aşağıdaki eklemeleri yap.
<uses-permission android:name=”android.permission.NFC”/>
<uses-feature android:name=”android.hardware.nfc” android:required=”true” />
Flutter Projesinden Android apk oluşturma (Visual Studio Code)
Terminal -> Run Build Task -> flutter build apk

Flutter XML verinin JSON dönüşüm işlemi
Servisten dönüşüm xml formatındaysa postman’da headers içinde Accept özelliği application/json;odata=verbose olarak eklenirse dönüş json olur. Kod içinde de şu şekilde bir çağrı yapılabilir.
final response = await http.get(
Uri.parse('https://example.com/api/data'),
headers: {
'Accept': 'application/json',
},
);
SharePoint Listenin Filtrelenmesi
Projemizde kullandığımız bir servis bize SharePoint listesi döndürüyor olsun. Şöyle bir servis url’i vardır: https://sub.mainadres.com.tr/_api/Web/Lists(‘guid’)/items
Bu servis bir xml veri döner. Header altında Accept kısmını application/json;odata=verbose olarak değiştirdiğimizde json veri döner.
Filtereleme örnekleri şu şekildedir;
Bu json veride HaberTarihi alanı olsun. Bir haber tarihinden (2020-12-12) sonraki verileri almak istiyorsak;
https://sub.mainadres.com.tr/_api/Web/Lists(‘guid’)/items?$filter=HaberTarihi gt ‘2020-12-12’
boolean bir AktifMi alanı olsun. Bu değerin true olduğu verileri almak için;
https://sub.mainadres.com.tr/_api/Web/Lists(‘guid’)/items?$filter=AktifMi eq 1
Emulator VPN Bağlantı Durumu
Flutter uygulamasını android emulatör üzerinde test ettiğimizi düşünelim. Servise erişim için de bir vpn’e bağlanmamız gereksin. Vpn bağlantısı kurulduktan sonra servis status 200 dönüyorsa fakat emulatör failed host lookup gibi bir hata dönüyorsa şundan emin olmalısın; android emulatör vpn bağlantısı kurulduktan sonra çalıştırılmalıdır. Bu şekilde emulator de vpn ile ağa bağlanmış olur.
type ‘Null’ is not a subtype of type ‘int’
int değerinin beklendiği bir yerde null ataması yapılmaya çalışıldığında bu hata ortaya çıkar. Bunu düzeltmek için;
1- Değişkene şu şekilde atama yapılsın.
id: json[‘Id’] ?? 0, Burada ?? ile bir null kontrolü yapılır ve değer null ise id’ye 0 atanır.
2- Değişken tanımı yapılırken alan nullable yapılır.
final int? id;
Tarih ve Saat Bilgisini Ayrıştırma
Elimizde tarih-saat bilgisi içeren bir String olsun. 2023-09-26 T10:25:26Z gibi. DateTime nesnesini kullanarak tarih ve saat bilgisini ayrıştırabiliriz. Tarihi öncelikle DateTime nesnesine çeviririz. Sonra sadece tarih bilgisini alırız. padleft fonksiyonu ile de sabit bir uzunluk atanır ve bu uzunluğun altında kalan alanların başına 0 eklenir.(ya da başka bir karakter)
String tarihSaatString = "2023-09-26T10:25:26Z";
DateTime tarihSaat = DateTime.parse(tarihSaatString);
String sadeceTarih = "${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')}";
Emulator Storage Alanına Erişim
cd /Users/macbook/Library/Android/sdk/platform-tools
adb shell
/storage/emulated/0/Android/data
SingleScrollChildView Örnek Kullanım
Container(
height: screenHeight * 0.25,
margin: const EdgeInsets.symmetric(horizontal:20.0),
child: SingleChildScrollView(
child: Center(
child: Text(
announcementDetail.duyuruIcerik,
style:
CustomTextStyles.textStyleDarkBlue10_400,
),
),
),
),
initState Yaşam Döngüsü
initState StatefulWidget oluşturulduğu zaman çağrılır. StatefulWidget sınıfından türetilen bir state sınıfının oluşturulduğu anı temsil eder. initState içinde asenkron bir method varsa ve bu method içinde bir asenkron işlemin tamamlanmasını sağlamak için bir await varsa bu await tamamlanıncaya kadar widget ağacı oluşturulmaz diye bir şey yoktur. Widget ağacı yine oluşturulur ancak bir değişken ya da liste oluşturulduğunda bu setState ile kaydedilir ve bu şekilde widget ağacı yeniden oluşturulur.
Widget ağacı oluşturulduktan sonra örneğin bir state değişkeni asenkron method içerisinde yeni bir değer alabilir. Şu şekilde;
setState(() {
_dataLoaded = true;
});
Burada widget ağacı içinde _dataLoaded değeri güncellenir ya da başka bir işlem yapılır.
Benzer şekilde didChangeDependencies içinde bir değişiklik yapılabilir ve bu değişiklik sonrasında aşağıdaki setState eklemesi yapılarak widget ağacının yeniden oluşturulması sağlanır
setState(() {});
List Initialization
List<NewsListModel> newsList = [];
burada boş bir liste oluşturulur.
List<NewsListModel> newsList = [NewsListModel(), NewsListModel(), ..];
Burada da liste başlangıç değerleriyle doldurulur.
Widget Key
Her widget’ın benzersiz bir kimliğe ihtiyacı vardır. Bu kimliği sağlamak için Key kullanılır.
class MyCarouselItem extends StatefulWidget {
final NewsListModel newsItem;
const MyCarouselItem({Key? key, required this.newsItem}) : super(key: key);
@override
MyCarouselItemState createState() => MyCarouselItemState();
}
Key? key ifadesi ile widget’a benzersiz bir anahtar ataması yapılabilir. super(key: key) ile de bu anahtar StatefulWidget’a geçirilir.
Carousel Slider Paketinin Kullanımı
Carousel_slider paketi projeye eklenir.
carousel_slider: ^4.2.1 //örneğin
CarouselOptions özellikleri;
initialPage : carousel’in başlangıçta göstereceği sayfanın indeksi.
enableInfiniteScroll : carousel’in başı ve sonu olmadan sonsuz biçimde dönmesidir. Son eleman yana kaydırıldığında ilk elemana geçer. Sonda takılmaz ya da ilk eleman için aynısı geçerli olur.
viewportFraction : Carousel’de görünen her elemanın, Carousel’ın genişliğine oranını belirtir.
onPageChanged : sayfa değiştikçe çağrılacak fonksiyonu belirtir.
pageViewKey : Carousel’ın içindeki PageView’in bir anahtarını belirtir.
autoPlay : otomatik oynatma özelliğini belirtir.
enlargeCenterPage : orta sayfayı büyütmek istersek kullanırız.
aspectRatio : carousel’in en-boy oranını gösterir.
Empty Constructor
Bir sınıfın eğer required alanlar içeren bir constructor’ı varsa burada bir empty constructor aşağıdaki şekilde oluşturulur.
AnnouncementsListModel.empty() : id = 0, title = '', duyuruIcerik = '',
duyuruSirasi = 0, kategori = '', modifiedDate = '',
createdDate = '', authorId = 0, editorId = 0;
Sonrasında bu içerik widget içerisinde aşağıdaki şekilde çağrılır ve boş bir instance oluşturulmuş olur.
AnnouncementsListModel myEmptyInstance = AnnouncementsListModel.empty();
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag
ScrollView içindeki bir alanda klavye açıldıktan sonra aşağı ya da yukarı yönlü yapılacak bir scroll işleminde klavyenin otomatik olarak kapanması durumunu ifade eder. SingleChildScrollView içinde kullanılır.
physics: const BouncingScrollPhysics()
Scroll yapılan sayfanın sonuna ya da başına gelindiğinde bir geri tepme, geri sıçrama oluşturur. SingleChildScrollView içinde kullanılır.