Pandas DataFrame üzerinde loc ve iloc indeksleme yöntemleri

Pandas DataFrame üzerinde loc ve iloc indeksleme yöntemleri, verileri belirli satır ve sütunlara erişmek veya bu verileri işlemek için kullanılır. İşte bu yöntemlerin kullanımına dair örnekler:

Öncelikle, aşağıdaki gibi bir DataFrame’i ele alalım:

DataFrame içeriği:

1. loc Kullanımı:

loc yöntemi, etiket tabanlı indeksleme yapmak için kullanılır. Satır ve sütun etiketlerini kullanarak veriye erişim sağlar.

2. iloc Kullanımı:

iloc yöntemi, konum tabanlı indeksleme yapmak için kullanılır. Satır ve sütun indeksleri (sıfır tabanlı) ile veriye erişim sağlar.

Bu örneklerde, loc ve iloc kullanarak belirli satır ve sütunlara nasıl erişebileceğinizi ve bunları nasıl işleyebileceğinizi görebilirsiniz. Eğer verilerinizi daha karmaşık bir şekilde işlemek isterseniz, bu yöntemleri farklı senaryolara göre uyarlayabilirsiniz.

Kategori Pandas, Python
10.08.2023
63 Okunma

Pandas ile DataFrame Oluşturma Yolları

Pandas ile DataFrame Oluşturma Yolları

Pandas kütüphanesi, veri manipülasyonu ve analizi için oldukça popüler bir Python kütüphanesidir. Listeler, NumPy ndarrays (n-dimensional arrays) ve sözlükler üzerinden veri yapılarını DataFrame olarak dönüştürmek oldukça yaygın bir işlemdir. Aşağıda, listenizden, NumPy ndarray’den ve sözlükten DataFrame oluşturmanızı gösteren örnek kodları bulabilirsiniz:

Bu örneklerde, önce farklı veri yapılarını kullanarak DataFrame’ler oluşturulur. Daha sonra oluşturulan DataFrame, to_csv yöntemi ile CSV dosyasına kaydedilir. index=False parametresi ile index sütunu dosyada saklanmaz.

Bu kod parçacığı, listeler, NumPy ndarrays ve sözlükler kullanılarak nasıl DataFrame oluşturulacağını ve bunların nasıl CSV dosyasına kaydedileceğini göstermektedir. Gerçek verilerinizi bu örneklerdeki verilere göre düzenleyerek kendi senaryonuza uyarlayabilirsiniz.

Kategori Pandas, Python
10.08.2023
55 Okunma

R ile “data.frame” Komutu

R programlama dilinde “data.frame” veri yapısı, farklı veri tiplerini içeren bir tabloyu temsil etmek için kullanılır. Bir “data.frame”, her sütunun aynı uzunluktaki vektörlerden oluşan veri yapısını içerir. İşte “data.frame” kullanımına örnekler:

Yeni bir data.frame oluşturma:

Bu örnekte, “isimler”, “yaslar” ve “maaslar” adında üç farklı vektör oluşturuyoruz. Sonrasında bu vektörleri kullanarak “veriler” adında bir data.frame oluşturuyoruz. “veriler” data.frame’i, “Isim”, “Yas” ve “Maas” adlarında üç sütuna sahip olacak ve her bir sütun ilgili vektörlerin değerlerini içerecektir.

Mevcut verileri data.frame’e ekleme:

Bu örnekte, “veriler” data.frame’ine “sehirler” adında yeni bir sütun ekliyoruz. Bu sütun “Sehir” adını alacak ve “sehirler” vektörünün değerlerini içerecektir.

data.frame’den veri seçme:

Bu örnekte, “veriler” data.frame’inden 2. satırda yer alan “Maas” sütununun değerini seçiyoruz.

data.frame’de filtreleme:

Bu örnekte, “veriler” data.frame’indeki “Yas” sütununa göre 25 yaşından büyük olanları filtreliyoruz ve sonucu “filtreli_veriler” adında yeni bir data.frame’e atıyoruz.

Data.frame’ler, R dilinde verileri düzenlemenin ve analiz etmenin güçlü bir yolu olarak kullanılır. Veri bilimciler ve analistler, genellikle bu yapıyı veri tabloları şeklinde kullanarak verileri işlemek ve analiz etmek için kullanırlar.

Kategori Featured, R
30.07.2023
63 Okunma

“Gerçekten” nedir bu BLoC?

Merhabalar, uzun bir süredir yazmaya değer bir konu bulamamam sebebiyle yazılara ara vermiş oldum. Genellikle herkes tarafından yeterince değinildiğini düşündüğüm konuları yazmayı tercih etmiyorum. Yaklaşık 2 sene önce tanıştığım BLoC konusu için ise geç kaldığımı çünkü bu süre zarfında yeterince içerik yayınlanmış olabileceğini düşünmüştüm. Ancak son zamanlarda flutter öğrenmeye çalışan arkadaşlarıma en çok zorlandıkları konuyu sorduğumda “bloc” aldığım yanıtlar arasında hatrı sayılır bir yere sahipti. İtiraf etmek gerekirse benim de flutter yolculuğumda anlamakta ve verimli bir kullanım sağlayacak kadar hakim olmakta en çok zorlandığım konu kendisiydi. Tüm bunları göz önünde bulundurduğumda bu yazıyı yazmaya girişmiş bulundum 🙂 Kişisel olarak, bir konu anlatılırken sadece güçlü ve değerli teorik bilgilerin verilmesi mantalitesine sıcak bakamayanlardanım. Bana göre bir şeyi yapıyorsak “neden yapıyoruz” bunu bilmek gerekir ki (ya da ben fazla sorgulayıcıyım) yaptığımız şey hakkında, ilgili şeyi farklı senaryolarda da yorumlayabilecek kadar fikrimiz olsun. Ben de bu yazıda elimden geldiğince konunun mantığını, size puzzle çözer gibi hissettirmeden temiz bir şekilde aktarmak için elimden geleni yapacağım. Bunu yaparken yazılımsal kavramları yığınla kullanmaktan kaçınıp (e tabii kodlama kısmına kadar????) konunun mantığını öz olarak sunabileceğim bir dil kullanmaya çalışacağım 🙂

Neden BLoC kulllanalım ki?

Bu başlık altında BLoC’ın tarihçesine değinmek gibi bir niyetim yok şimdiden söyleyeyim 😀 Bu konuyu öğrenmek istiyoruz, evet ama neden ki? Neden bunu yapalım? Daha önce BLoC olmadan kod yazdıysanız backend kodları ve ui kodlarının iç içe, aynı class içinde olduğu durumlara aşinasınızdır. (Flutterı henüz yeni yeni öğrenmeye çalıştığım dönemde bu durum benim kafamı oldukça karıştırmıştı) Biz de istiyoruz ki bu spaghetti kodlardan kurtulalım, ui işlemleri ve backend işlemleri birbirinden ayrı yerlerde daha derli toplu, yönetilebilir ve test edilebilir olsun. İşte BLoC dediğimiz pattern, bunu gerçekleştirmek için geliştirilmiş bir kütüphane. BLoC bir state management kütüphanesidir. Bundan ne anlamalıyız? State management/durum yönetimi kavramını şöyle yorumlayabiliriz: Uygulamamızda oluşacak bazı aksiyonlar sonucu, uygulamamızın o an bulunacağı “durum”lara hakim olup birtakım değişiklikler gerçekleştirmek. O halde BLoC bizlere birtakım “olay”lar karşısında birtakım “durum”lar üretme olanağı sunar.

Yavaş yavaş konuya girelim…

Birtakım “olay”lar karşısında, birtakım “durum”lar üreteceksek eğer bizlere olaylar, durumlar ve bunları birbiri ile ilişkilendireceğimiz, mantık akışını yaratacağımız bir alan/bağlam gerekir. (İşin özü aslında bu cümleden ibaret :)) Olaylar, durumlar ve aralarındaki ilişki… Hmm o zaman bunları biraz konuya uyarlayalım. İşte biz bu “olay, durum, mantık akışı/ilişki” kavramlarını tam olarak BLoC patterninde yer alan events, states ve bloc sınıfı ile yapıyoruz/yapacağız.

Event, States, BLoC Sınıfları

Event classları bizim olaylarımızı, state classları durumlarımızı temsil ederken BLoC sınıfımız ise işin logic kısmını üstlenip “arayüz ve backend” arasında adeta bir arabulucu görevi görecek. Bildiğimiz üzere kullanıcıların uygulamalar ile etkileşimi arayüz katmanında gerçekleşir. Biz de kullanıcının hareketlerine göre bir ‘şeyler’(!) gerçekleştiririz. O halde arayüzümüzden bloclara (ilgili bloc sınıfları) “bak user x butonuna tıkladı” gibi haberler göndereceğiz. (Tabii ki bazen kullanıcıdan bağımsız, programda farklı sınıf ve blocların haberleşmesi de söz konusu olabilir.) BLoC sınıfımız ise bu haberin geldiğini tespit ettiğinde servisler, databaseler, helperlar vs. ilgili sınıflara gidip gerekli bilgileri, aksiyonları alacak, gerekli işlemleri başlatacak ve sonrasında da bu konuyla ilgilenen kim varsa “ben gerekli işlemleri başlattım ve şu an x aşamasındayım (x durumunda/x stateinde)” diyecek (state bildirimi). Bunu duyan sınıflar da ilgili state’e göre gerekli ise bir işlem başlatacak ya da ui güncelleyecek. Konunun mantığını biraz olsun anladık varsayıyorum. (Kabaca user interaction yada app akışı-> bir event üretir -> BLoC -> state üretir -> ui, listenerlar, diğer sınıflar vs. bu bilgiyi kullanır diyebiliriz.)

E dinlemek diyoruz, haber vermek diyoruz, ui güncellemek diyoruz. Peki nasıl yapacağız bunları? Size dinlemek için listenerlar olduğunu, state/duruma göre ui oluşturmak için builderlar olduğunu söylesem konunun aslında ne kadar İngilizce/Türkçe insan dili olduğunu görebilirsiniz sanırım. BLoC patterninde konuştuğumuz her şeyin karşılığı var. Listener (dinleyici), builder (oluşturucu) vs. bu componentler, bize anlatılanları, yazılım tarafında gerçekleştirmemize yardımcı olacak. Hadi o zaman bunlara bir göz atalım.

BLoC Componentleri

BLoC öğrenirken belki de en çok zorlandığım şey componentlerin mantığını iyi oturmaktı. Neyi ne zaman kullanacağımı birilerinin kodlarını inceleyerek çözmeye çalışmak ve anladığımı sandığım yerde kendi projem için uygun bloc yapısını oluşturamamak… (Fizik hocasının çözümünde mantıklı gelen formülü, başka soruda uygulayamamak gibi bir şey…) BLoC pattern biraz da deneyimledikçe optimal kullanıma ulaştığımız bir konu aslında.

BLoC Provider/Multi Bloc Provider:

BlocProvider adı üzerinde bir sağlayıcıdır. Bloc providerlar bize ilgili blocımızı context içerisinde kullanmayı sağlarlar. Bunu bir nevi ilgili blocımızı, uygulamamızın contextine kayıtlandırıyormuşuz gibi düşünebiliriz. Sonuçta kayıtlanmamış şeylerin varlığından haberimiz olmaz ve kullanamayız. BlocProvider.of<T>(context) bize context üzerinden ilgili bloc nesnemize erişim verir. Blocımıza ait bir provider tanımlamadan o blocı ilgili context içinde kullanamayız. Burada BlocProviderın bloca, oluşturduğumuz contextin sub-treelerinde/alt ağaçlarında erişim verdiğini unutmayalım. Yeni başlayanlar bu konsepti anlamadığı için güzel hatalar alabilir 😀 (kod bölümünde örneklendirdim)

MultiBloc provider ise birden fazla bloc providerı kullanmaya olanak sağlayan bir widgettır. Birden fazla bloc providerın kullanılması gereken senaryolarda iç içe bloc providerlar oluşturmaktan kurtulup daha düzgün kodlar elde edebiliriz. Eğer uygulamamızda birden fazla bloc varsa birbiri içine providerlar yazmak yerine hepsini liste içinde parametre olarak alan tek bir multi bloc provider yazmamız çok daha düzgün bir kod elde etmemizi sağlayacaktır. Aynı zamanda yönetimlerinin kolaylaşması da söz konusu olur. (Ekleme, çıkarma vs.)

BLoC Listener:

Her kavramın isimlendirmesi adeta bir özet gibi. Bloc listenerlar bizim blocımızdaki “değişimleri dinlememizi” sağlayan componentlerdir. Bloc listenerlar genellikle durumlardaki değişimlerin takibi için kullanılır. Listenerların tetiklenmesi için “değişim” gerekir. Bu davranış biçimini, yazdığımız kodlarda loglama yaparak gözlemleyebiliriz. Ne gibi?

Bu şekilde listenerlarımızın içine eklediğimiz custom loglar, başlarda nasıl davrandığını anlamak için yardımcı olabilir.

BlocListener, örneğin bir hata durumunda uyarı ekranına ya da hata ekranına yönlendirme gibi işlem yapılacaksa kullanılır. Burada işin Türkçesi şudur:

BlocA blocını sürekli dinleyen bir dinleyicimiz BlocA’nın durum değişimlerinden haberdardır. Örneğin BlocA bir başlangıç durumunda iken bir hata durumuna dönüşmüşse bu hata durumunun Bloc tarafında emit edildiği anda bunu yakalar.

Yine bu listener, dinlenen durumlar içerisinde yakalamak istediği bir x durumu olduğunda yapmak istediği bir işlem varsa bunu gerçekleştirir.

Kabaca bir örnek verelim ve açıklayalım.

BlocListenerlar her blocı dinleyemez değil mi? Hangisini dinleyeceğini belirtmemiz gerekir. (generic type bildirimi) Burada şunu diyoruz: sen BlocA’yı dinliyorsun evet ve eğer bir fail durumu yakalarsan ben uygulamamın error sayfasına yönlenmesini isterim, bu sebeple bu condition/şartım gerçekleştiğinde ilgili fonksiyonumu çağır.

Şununla karıştırmayalım: Bloclarımızın hangi eventta hangi duruma geçtiğini loglamak istersek bunun için bloc observer kullanırız. Buna kod bölümünde değineceğim.

BLoC Builder:

Bloc konseptinin en çok kullanılan bileşenlerinden biri bloc builderdır. Bloc builder, içinde builder fonksiyonunu bulunduran (ki bu fonksiyon mutlaka bir widget döndürmelidir.) bir bileşendir. Bloc builder, bize state’e göre bir widget gösterme olanağı verir. Bu bileşenlerin nasıl kullanılacağı ile ilgili örnekleri vereceğimiz için şimdilik ne amaçla kullandığımızı bilmekle yetinebiliriz.

Multibloc Listener:

Eğer aynı contextte farklı birkaç bloc listenera ihtiyaç duyuyorsak, bunları multibloclistener çatısı altında tutabiliriz. (MultiBlocProvider da bu konsepte sahip) Multibloc listener, birden fazla bloc listenerı liste olarak parametre alan bir componenttir. Multibloc listenerı kullanarak iç içe bulunan bloc listener widgetlarından kurtulup daha okunulabilir bir kod parçası yazabiliriz.

BLoC Consumer:

Bloc Consumer, eğer bir bloc için hem listener hem de buildera ihtiyaç duyuyorsak ikisini bir arada kullanmamızı sağlar. “E zaten hem listener hem buildera ihtiyacım varsa ikisini de iç içe oluştururum, consumera ne gerek var?” derseniz bu da bir tercih olabilir tabii. Zaten bloc consumer da koddaki gereksiz iç içe kullanımlardan kurtarmak amacıyla kullanılan bir widgettır. Yani iç içe listener ve builder da yazabiliriz, direkt bloc consumer da kullanabiliriz. Tabii burada tercih bloc consumer olsa daha doğru bir kullanım olur ????.

Kodlara Dökelim 🙂

Hadi şimdi tüm anlattıklarımızı darta dönüştürerek biraz pekiştirme yapalım… Öncelikle boş bir flutter projesi oluşturalım. Ve bloc paketimizi yaml dosyamıza ekleyelim.

Hem bloc builder kullanmanın mantıklı olacağı use caseleri barındıracak hem de birden fazla state/duruma ihtiyaç duyacak bir proje konusu ne olabilir diye düşündüğümde aklıma hava durumu uygulaması geldi. Burada api isteklerini beklerken farklı sonuç geldiğinde farklı bir ui gösterebiliriz.

En basit haliyle bir hava durumu uygulaması yaratmak için öncelikle bize bir hava durumu blocı gerekir. Aynı zamanda isteklerimizi atmak için bir servisimiz olsun. (Burada amaç blocın özünü anlatmak olduğu için konseptten kopmamak adına uygulamaya çok işlevsellik katmayacağım.) Bir de api’ye istek atıp response’u parse edebileceğimiz bir modelimiz olacak. Bloc sınıfları dışındaki sınıfların üzerine çok düşmeyeceğiz. Şunu biliyoruz: Bir bloc pattern için events, states ve bloc sınıfı olmak üzere 3 ana sınıf gerekir. O halde şimdi gerekli dosyalarımızı oluşturalım.

Bloc Yapısı için Sınıfları Oluşturmak:

Öncelikle ön hazırlık olarak apiye istek atmak için birer request, response ve apiden dönen bilgileri parse edeceğim info modeli oluşturdum. Sonrasında bu apiye istek atacağımız bir servis sınıfımız var. Şimdi bloc tarafını düşünelim. Neler gereklidir? Bizi zorlamayacak bir mimari oluşturmak için önceden potansiyel senaryoları düşünmek oldukça önemlidir.

Kendi deneyimlerimden çıkardığım bir sonucu sizlerler paylaşmak istiyorum, eğer bir işlemi bloc ile gerçekleştirirken karmaşık geliyorsa ya da süreci yönetmekte zorlanıyorsanız muhtemelen olayları, durumları kısacası mimariyi uygun şekilde oluşturmamışsınız demektir. Bu yüzden bloc pattern ile çalışırken öncelikle gerçekleşecek/gerçekleşebilecek olayları ve durumların taslağını çıkarmak önemlidir. Tabii ki sonrasında projenin ihtiyacına göre değişiklikler gerekir fakat ilk oluşturma için bu durum önem arz eder.

Events Sınıfı

Öncelikle events sınıfımızı göz önünde bulunduralım. Bunun için ilk olarak soyut bir olaylar sınıfı oluşturacağız sonrasında bundan extend edilen asıl olay sınıflarımızı ekleyeceğiz. Şu an için olayımız usera göstermek adına hava durumu bilgilerini getirmek olabilir. O halde blocımız için event sınıfımızın adı EventWeatherGetInfo olabilir. Biz bu sınıfı bloca bildirip ‘bize şehrin hava durumu bilgilerini getir’ diyeceğiz. O zaman bizim bu eventı bloca bildirirken hangi şehirden bahsettiğimizi de söylememiz gerekir değil mi?

Bu durumda bu sınıfımıza bir şehir bilgisi alanı girmeliyiz ki bu bilgiyi bloc tarafa taşıyabilelim.

İşte şimdi events sınıfımız tamamlandı. Peki neden abstract class oluşturduk ya ezbere mi yapıyorsun bunu? Yoo, hemen söyleyelim. Biz işin logic kısmını yapmak için Bloc sınıfımızı oluştururken aslında bloc paketimizde bulunan Bloc sınıfımızdan miras alacağız. Bu miras alma esnasında generic typeımızda event ve state bildirimi yapmamız gerekmekte. NEDENNN? Çünkü eğer bu generic type bildirimini yapmazsak oluşturacağımız bloc sınıfımız <dynamic, dynamic> tipe sahip bir bloc olur. Bu da bizim belirlediğimiz state ve event classlarının tipiyle uyuşmazlık yaratır ve birçok componenti kullanırken bu konuyla ilgili hata alırız.

Bir event sınıfını generic type olarak vermemiz gerekiyor ama bizim bir çok eventımız var (şu an için bir tane olsa da başka projelerde birden fazla olacak) e hangi birini vereceğiz? İşte bunun için tüm olaylarımızı temsil edecek soyut bir sınıf oluşturup bunu blocımıza bildiriyoruz. Sonrasında örnekte de gördüğümüz gibi yeni bir olay sınıfı yaratmak isterken de bu abstract classımızdan miras alıyoruz ki bu generic typeımız ile bir uyuşmamazlık yaşamayalım. Aynı durum stateler için de bu şekildedir. Sanırım şimdi oldu 🙂 Hadi devam edelim.

Stateler…

Gelelim state sınıflarımıza. Stateler, appimiz için o bloc bünyesinde yaptığımız eylemler sonucunda oluşabilecek durumları temsil eden sınıflardır. Şimdi kendi use caseimizi düşünelim. Ne yapıyoruz? Bir apiye istek atıp bazı hava durumu bilgilerini alıyoruz. Bu durumda ne olabilir ki? Birincisi başarı ile bu isteği atıp, sonucu alıp kullanıcıya bunu gösterebiliriz. İkincisi, bu isteği atarken bir hata alabiliriz ve kullanıcıya bir hata meydana geldiğine dair bilgilendirme yapabiliriz. O halde bunları göz önünde bulundurarak 2 adet durum oluşur diyebiliriz. Bir de apiden istek dönene kadar bir bekleme durumu oluşabilir. Böylece 3 adet durumumuz var diyebiliriz. Peki ya herhangi bir olayı henüz tetiklememişken bloc sınıfımızdan bir bloc nesnesi üretip kullanıma hazır hale getirirken o esnada durum ne olur? Bu durum için de bloc sınıfımıza bir başlangıç durumu atayabiliriz. Böylece artık 4 durum sınıfı oluşturmamız gerektiğini anladık. Şimdi bir de şunu düşünelim bloc sınıfımıza eventımız vasıtasıyla “kullanıcı x şehri için hava durumlarını istiyor, bunları getir” dedik. Bloc sınıfımız ise bir arabirim, haberci gibi davranarak ilgili api servisine bu isteği iletip sonucu alacak ve app bazında “artık sonuçlar hazır” ya da “apiden sonuçları getirirken hata çıktı” gibi durumlara dönüştürecek. Bu durumda, bunları bildirirken eğer istek başarılıysa bu başarılı sonucun değerlerine erişebilmeli ve bir WeatherInfo (api responseunu parse etmek için oluşturduğumuz model sınıfı) sınıfı nesnesi aracılığıyla ilgili bilgilere sahip olmalıyız. Burada yazdığımız apinin responseunu incelemekte fayda var. Örneğin bizim kullanacağımız api 7 günlük bir hava durumu bildirimi sunar. Dolayısıyla burada kullanıcıya bir List<WeatherInfo> değişkeni üzerinden bilgileri göstermemiz gerekir. Aynı şekilde bir hata durumunda kullanıcıya hata mesajımızı göstermek istiyorsak, bunun için de failed durumuna bu mesajı atayabileceğimiz bir alan vermemiz şarttır.

Bu bilgiler ışığında statelerimizin son hali:

şeklinde olur diyebiliriz.

NŞA’da kodlama yaparken naming convention benim için oldukça önemlidir. State sınıfı için ise naming conventionda isimlerin kullanılması önerilir çünkü bahsi geçen durum bir nevi o “an”ın temsilidir. Örneğin bir işlem tamamlanmışsa ProcessCompleted değil ProcessComplete olmalıdır. Ancak ben state sınıflarımı kişisel insiyatifimle bu şekilde anlandırıyorum. Lütfen siz naming conventionları buradan inceleyin. Sonrasında kendi kararınızı verin 🙂

Bloc Sınıfı

Gelelim işin logic kısmının döndüğü asıl sınıfımız olan Bloc sınıfımıza. Projenin akışını, eventları, stateleri vs. önceden düşünüp iskeletimizi oluşturduktan sonra bloc sınıfımızı yazmak oldukça kolay olacaktır. (en azından bu ölçütte bir proje için :D) Önceden bloc sınıfı mapEventToState adında eventları state’e dönüştüren ve stateleri yield eden streame sahipti. Burada developerlar için, stream, yield, yield*, async* gibi kavramların öğrenme yükünü azaltmak, iç içe async işlemlerde hangi durumun olacağının bazen öngörülememesi gibi sebeplerle stream yerine “event handler”ların kullanılmasına karar verildi.

Event handlerlar (on<YakalanmasınıİstediğimizEvent>) hangi olayda ne işlem yapacağımızı bildirmemize olanak sağlar. Böylece olay karşısında alınacak aksiyonun öngörülebilir olması için bir olay ile ((Event event, Emitter<State>) {} şeklinde) bir callbacki eşleştirebiliriz. Bu callbackler asenkron olabilir. Aynı zamanda callback üzerinden tetiklenen event/olaya erişebildiğimiz için o eventın field değerlerine de erişebiliriz. Ne demek istiyorum?

Bloc sınıfımız yukarıdaki gibi. Özetlemek gerekirse bloc için bir constructor tanımladık ve default olarak initialize durumu ile ilgili bloc nesnemizi başlatmaya olanak sağladık.

Satırı ile bir event handler tanımladık. Aslında burada, eğer EventWeatherGetInfo eventını yakalarsan _getWeatherInfo callbackini tetikle şeklinde bir tanımlama gerçekleştirdik. Şimdi bu callback değerimizi inceleyecek olursak…

Buradaki kodun oldukça okunabilir olduğunu düşünüyorum ancak özetlemek gerekirse: Öncelikle asenkron bir işlem başlatacağımız ve bunun ne kadar süreceğini bilemediğimiz için hızlıca bir bekleme durumuna geçtiğimizi belirten statei emit ediyoruz. (Aslında bloc builderı anlatmak için biraz bahane :)) Sonrasında apiye istek atıyoruz. Sonucumuz başarılı ise başarılı olma durumuna geçip bu ilgili statein de fieldına responsedan dönen bilgimizi (hava durumları listesi) veriyoruz. Eğer başarılı değil ise de fail stateine geçip yine errorMessage olarak constructorına eklediğimiz değeri giriyoruz.

Burada eventın fieldına nasıl eriştiysek (event.city kullanımı) state sınıflarına field olarak verdiğimiz bu değerlere de ui tarafında aynı kullanım ile erişeceğiz (state.errorMessage gibi).

Artık bloc sınıfımız hazır. Umarım neyi neden yaptığımızı ve nasıl yapacağımızı anlamışsınızdır 🙂 (Anlamadıysanız da sorun değil, buyrun iletişime geçelim). Artık anlatımımıza UI kısmıyla devam edebiliriz.

UI, BLoC Componentleri

Bloc mimarimizi oluşturduk, şimdi ise bunu projenin presentation katmanında nasıl kullanabiliriz sorusuna bakalım.

Şimdi böyle baya ince düşünülmüş bir UI’ımız olsun 😀 (Kodların ss olmasına takılmayalım repoyu paylaşacağım. )

Burada, butonumuza tıkladığımızda tetiklenecek bir fonksiyonumuz var, gördüğümüz üzere adı da _getWeatherInfo(). Biz bu fonksiyon içerisinden ilgili blocımıza bir event göndereceğiz. Bunu gönderirken textfieldımız içerisindeki şehir bilgisini de ileteceğiz.

Bloc tarafta bir eventı nasıl yakaladığımızı (event handlerlar ile) anlatmıştım. Peki bloc’a eventı nasıl iletiriz? Bunun için Bloc nesnesi üzerinden .add(EventSınıfımız(field: fieldDeğerimiz)) şeklinde bir kullanım yapabiliriz. Bir başka deyişle add ile bloclarımızda olay tetikleme gerçekleştiririz. O halde bizim bunu yapmak için bu bloc değerine erişimimiz gereklidir. Alt ağaçlardan bloc nesnesine erişmek için bloc provider üzerinden bir bloc sağlayıcı oluşturmamız gerekir ki biz bu blocı kullanabilelim. Ben bu providerımı, üzerinde çalıştığım PageMain’imi kapsayan main widgetta ekledim ki alt ağaçlardaki contextler üzerinden erişimimim olabilsin.

Şimdi peki bu provider üzerinden PageMainimde nasıl bir erişim gerçekleştirebilirim? Bunu şöyle yapabiliriz. Main sınıfımızın init state’i içerisinde contextten okunup alınmak üzere bir BlocWeather tipinde nesne oluşturabiliriz. Şöyle ki:

late ile sonradan değerinin atanacağını bildirip, initStateimizde bu atamayı gerçekleştirdik.

İlgili butonumuzun fonksiyonu içerisinde de yukarıdaki gibi bir kullanımla olayımızı tetikleriz. Ne yapıyoruz? add ile bir nevi “sana şu olayı gönderiyorum“ mesajını blocımıza iletiyoruz. Buradaki _textController.text ifadesi ise daha önce EventWeatherGetInfo sınıfımız için oluşturduğumuz city değeridir, bunu constructorda set ediyoruz. İşte bu kadar basit.

Şu ana kadar söz konusu iletişimi nasıl yapacağımızı düşündük. Bir de şöyle bir şey gerçekleştirelim: Butonumuzun hemen altında, bize bilgi gelirken bir yükleniyor ibaresi görünsün, sonuç geldiğinde ise bu bilgileri görelim. O halde aslında burada ne oluyor? Önceden belirlediğimiz bloc statelerine göre farklı widgetlar gösterme gereksinimi duyuyoruz. Dikkat ederseniz bu use case tam olarak BlocBuilderın tanımındaki senaryoya örnektir. Bu sebeple butonumuzun hemen altına bir bloc builder eklememiz gerektiği sonucunu çıkarabiliriz.

Uygulamamızın ilgili bölümünde, builderımız içerisinde kendi koyduğumuz state conditionlarına göre istediğimiz widgetları döndürmeliyiz. O halde yukarıda önceden tasarladığımız akışa göre return edeceğimiz widgetlarımızı ekleyelim:

Artık uygulamamızı tümüyle tamamladık.

Eğer main.dartta providerımızı tanımlamasaydık: BlocProvider.of() called with a context that does not contain a BlocWeather. şeklinde bir hata alacaktık.

Tüm yaptıklarımız sonucunda uygulamamızın son hali:

Yazı burada bitiyormuş gibi görünüyor (ben de bitti sanmıştım ????) ama son olarak bloc kullanırken hangi olayın tetiklendiğini, hangi duruma geçildiğini kısacası blocımız içerisinde neler olup bittiğini anlamımızı sağlayacak bloc observerdan da bahsedelim.

Bloc Observer

Bloc observer sınıfı bloc paketinde bulunan ve içerisinde bloclarda gerçekleşen error, change gibi durumları alarak bazı işlemler gerçekleştirmemizi sağlayan, kısacası bloc/larımızı gözlemlemiz için kullanılan bir soyut sınıftır. Uygulamalarımız için bu sınıfın metotlarını override ederek kendi custom observer sınıfımızı yazabiliriz.

Bunun için:

şeklinde BlocObserverdan miras alan CustomBlocObserver sınıfı oluşturabiliriz. Burada her metodu override etmek zorunda değiliz, ihtiyaç duyduklarımız bizim için yeterli olacaktır. Ben 3 önemli metodu override ederek sınıfımızı tamamlıyorum.

Sınıfımızı oluşturduk bir de sınıfımız ile Bloclar arasında bir bağlantı gerekir. Bunu da main metodumuz içerisinde gerçekleştirebiliriz. Böylece:

olan sınıfımıza

ilgili satırı ekleyerek bu bağlantıyı tamamlamış oluruz.

Tüm sürecin sonunda artık loglarımızda ‘bloc observer output’ görselinde de görüldüğü gibi blocımızın state geçişlerini vs. daha rahat gözlemleme şansı elde etmiş olduk.

Yazımızı burada noktalayabiliriz. Umarım işin temelinin nasıl bir mantıkla işlediğini aktarabilmişimdir, teşekkürler 🙂

Herhangi bir soru için LinkedIn üzerinden iletişime geçebilirsiniz.

Proje repoya buradan erişebilirsiniz. Ya da direkt tıklayarak indirebilirsiniz.

Daha fazlası için: resmi dokümandan yardım alın.

Kaynak : “Gerçekten” nedir bu BLoC?. Merhabalar, uzun bir süredir yazmaya… | by Burcu S | Medium

Kategori Featured, Flutter
12.05.2023
72 Okunma

Flutter’da Sayfalar Arası Geçişler

Flutter’da tek sayfa tasarımını yapmak kadar, oluşturulan çoklu sayfalar arasındaki geçişi sağlamak da önemlidir. Bazen bir sayfadan diğerine geçerken, önceki sayfaya geri dönülmesini istemeyebiliriz ya da bir sayfada kullanıcıdan edindiğimiz bir bilgiyi, başka bir sayfada kullanmak isteyebiliriz.

Bu makalede sizlere Flutter’da sayfalar arası geçişlerin nasıl yapıldığıyla ilgili ayrıntıları aktaracağım. Basit olanından, ayrıntılı olanına doğru bir yolculuğa çıkacağız.

1) Navigator.push & MaterialPageRoute & Navigator.pop

İlk olarak sayfalar arası geçişler için Navigator sınıfını kullanacağız. Bu amaçla üç sayfalı bir örneği incelemekle başlayacağız. Şimdi bu konuya özel Flutter’da yeni bir proje başlatın ve aşağıdaki gibi; Sayfa 1Sayfa 2 ve Sayfa 3 şeklinde üç sınıf oluşturun. Bu üç sayfayı sadece geçişler için kullanacağımızdan herhangi bir içerik girmemize şimdilik gerek yok.

Kodu çalıştırdığımızda Sayfa 1 sınıfı inşa edilecektir ve ekranda aşağıdaki sayfa gözükecektir.

Ekranda bulunan Sayfa 2’ye Git düğmesine basıldığında Navigator.push(…) constructor’ı (yapıcı metodu) tetiklenmiş olacaktır.

Navigator.push iki parametre almaktadır. Biri context, diğeri de yeni sayfayı inşa etmeye yarayan MaterialPageRoute sınıfıdır.

MaterialPageRoute ile anlık olarak bir sayfa tasarımı sunulup, önceki sayfadan gelen kullanıcı, yeni oluşturulan sayfaya yönlendirilmiş olur. Yeni sayfanın özellikleri, MaterialPageRoute içerisindeki builder: parametresi ile verilir.

Sayfa2 sınıfı daha önceden hazır olduğu için builder parametresindeki fonksiyon, direkt olarak Sayfa2‘ye döndürülür.

MaterialPageRoute(builder: (context) => Sayfa2())

Böylece birinci sayfadan, ikinci sayfaya geçiş yapmış olduk.

İkinci sayfada iki buton bulunmaktadır. Bunlardan biri Geri dön! diğeri de, Sayfa 3’e Git! butonudur. Üçüncü sayfaya geçiş yapmamızı sağlayan butonda, bir önceki sınıfta olduğu gibi, Navigator.push komutu bulunmaktadır. Birinci sayfadan, ikinci sayfaya nasıl geçtiysek, ikinci sayfadan üçüncü sayfaya da aynı mantıkla geçebiliriz.

Fakat yeniden birinci sayfaya geri dönmek istersek, Navigator.pop(…) komutunu kullanmamız gerekir.

Geri dön! butonuna basıldığında, onPressed parametresinde görebileceğiniz gibi,

onPressed: () => Navigator.pop(context)

ifadesi yer alır. (Sayfa2 sınıfı, 37. satır) Bu sayede istersek ilk sayfaya geri dönebiliriz. Geri dönme işlemini bu butonla yapabildiğimiz gibi, cihazımızda bulunan Geri düğmesi ile de aynı işlemi yapabiliriz. Ayrıca tasarımımızda bir AppBar kullandığımız için, otomatik olarak AppBar üzerinde de bir geri dönme butonu aktif olacaktır. Üstteki resimde geri dönme işlemini yapabileceğimiz üç bölge kırmızı yuvarlakla gösterilmiştir.

Böylece üçüncü sayfaya gelmiş olduk. Sayfa 3 sınıfında da görebileceğiniz gibi, üçüncü sayfada sadece bir Geri dön! butonu bulunur ve bizi ikinci sayfaya taşır.

Bu şekilde hazırladığımız bu üç sayfa arasında kolaylıkla geçiş yapabildik. Şimdi biraz daha ayrıntıya girelim.

Kaynak : Flutter’da Sayfalar Arası Geçişler | by Zeki ÇIPLAK | Flutter Türkiye | Medium

Kategori Featured, Flutter
08.04.2023
139 Okunma

Flutter Timer Sınıfı

Flutter Timer, bir uygulamada zamanlama işlemlerini gerçekleştirmek için kullanılan bir sınıftır. Flutter Timer, belirli bir süre sonunda işlemlerin gerçekleştirilmesini sağlar. Bu makalede, Flutter Timer ile ilgili tüm fonksiyonları ele alacağız.

Flutter Timer’ın Temel Kullanımı

Flutter Timer, dart:async kütüphanesi altında yer alan Timer sınıfından türetilmiştir. Timer sınıfı, bir işlemi belirli bir süre sonra yürütmek için kullanılır. Flutter Timer, Timer sınıfına ek olarak, süreye bağlı olarak tekrarlayan işlemler gerçekleştirmek için tasarlanmıştır.

Flutter Timer’ın temel kullanımı aşağıdaki gibi olacaktır:

Bu kod, 5 saniye sonra konsola “Flutter Timer” yazdıracaktır.

Flutter Timer’ın Çalışma Prensibi

Flutter Timer, bir işlemi belirli bir süre sonra yürütmek için kullanılır. Timer sınıfından türetilmiş olan Flutter Timer, süreye bağlı olarak tekrarlanan işlemler gerçekleştirmek için tasarlanmıştır. Flutter Timer, zamanlayıcı işlemi gerçekleştirmek için bir işlev alır. Bu işlev, zamanlayıcı süresi dolduğunda çalıştırılacaktır.

Flutter Timer, başlat () yöntemi çağrıldığında zamanlayıcıyı başlatır. Başlat () yöntemi, iki parametre alır: süre ve işlev. Süre, zamanlayıcının çalışma süresini belirlerken, işlev, zamanlayıcının süresi dolduğunda gerçekleştireceği işlemi belirler.

Flutter Timer’ın Özellikleri

Flutter Timer, birçok özellik içerir. Bu özellikler, zamanlayıcının işlevselliğini artırmak için tasarlanmıştır. Aşağıdaki özellikler, Flutter Timer ile ilgili en önemli özelliklerdir:

  • Süre: Süre, zamanlayıcının çalışma süresini belirler. Süre, Duration sınıfından türetilir. Duration sınıfı, zaman aralıklarını ve süreleri temsil etmek için kullanılır.
  • İşlev: İşlev, zamanlayıcının süresi dolduğunda gerçekleştireceği işlemi belirler. İşlev, Function
  • Tekrarlayan İşlemler: Flutter Timer, tekrarlayan işlemler gerçekleştirmek için tasarlanmıştır. Bu özellik, zamanlayıcının süresi dolduğunda işlevi tekrarlayarak, belirli bir süre boyunca işlemleri gerçekleştirmesini sağlar.
  • İş Parçacığı: Flutter Timer, varsayılan olarak ana iş parçacığında çalışır. Bu nedenle, zamanlayıcı işlemleri ana iş parçacığında gerçekleştirilecektir. Ancak, zamanlayıcı işlemleri farklı bir iş parçacığında gerçekleştirmek için de yapılandırılabilir.

Flutter Timer’ın Fonksiyonları

Flutter Timer, birçok fonksiyona sahiptir. Bu fonksiyonlar, zamanlayıcının işlevselliğini artırmak için tasarlanmıştır. Aşağıdaki fonksiyonlar, Flutter Timer ile ilgili en önemli fonksiyonlardır:

  • start(): Zamanlayıcıyı başlatmak için kullanılır. Bu yöntem, zamanlayıcının süresi dolduğunda gerçekleştirilecek işlemi belirler.

  • cancel(): Zamanlayıcıyı iptal etmek için kullanılır. Bu yöntem, zamanlayıcının süresi dolduğunda gerçekleştirilecek işlemi iptal eder.

  • isActive: Zamanlayıcının aktif olup olmadığını belirlemek için kullanılır. Bu yöntem, zamanlayıcının aktif olup olmadığını kontrol eder ve true veya false değerleri döndürür.

  • periodic(): Sürekli olarak tekrar eden işlemler için kullanılır. Bu yöntem, zamanlayıcının süresi dolduğunda gerçekleştirilecek işlemi tekrarlayarak, belirli bir süre boyunca işlemleri gerçekleştirir.

Flutter Timer, mobil uygulama geliştiricilerinin zamanlama işlemlerini gerçekleştirmek için kullanabilecekleri çok yönlü bir araçtır. Flutter Timer, belirli bir süre sonunda işlemlerin gerçekleştirilmesini sağlar ve tekrarlayan işlemler için özellikler içerir. Bu makalede, Flutter Timer ile ilgili tüm fonksiyonları ele aldık ve kullanımı hakkında bilgi verdik.

Aşağıdaki örnekte, kullanıcının belirlediği bir süre boyunca geri sayım sayacı çalışacak ve her saniye güncellenecektir:

Yukarıdaki örnekte, _startTimer fonksiyonu, kullanıcının belirlediği süreye göre geri sayım süresini ayarlar ve _timer değişkenine bir Timer.periodic nesnesi atar. Timer.periodic fonksiyonu, belirli bir aralıkta geri sayım yapmak için kullanılır. Her saniye, geri sayım değeri bir azaltılarak, _secondsRemaining değişkeni güncellenir ve ekranda gösterilir. Geri sayım sıfıra ulaştığında, _timer iptal edilir.

Scaffold içinde, geri sayım değeri ekranda gösterilir ve ElevatedButton üzerinde tıklanarak geri sayım başlatılır. Yukarıdaki örnek, Flutter Timer kullanarak basit bir geri sayım sayacı oluşturmanın temelini göstermektedir. Bu örneği istediğiniz gibi değiştirebilir ve özelleştirebilirsiniz.

Aşağıda saat,dakika ve saniye cinsinden saatin son hali görünmektedir.

Kategori Featured, Flutter
29.03.2023
110 Okunma

Flutter Card Uygulaması

 

Kategori Featured, Flutter
25.03.2023
91 Okunma

Flutter TextStyle Kullanımı

TextStyle, Flutter’da metin öğelerine stil uygulamanın temel yoludur. Metin stilleri, örneğin font boyutu, renk, vurgulama ve ayrıştırma ayarları gibi metin öğelerindeki çeşitli özellikleri belirleyen bir nesnedir.

Öncelikle, bir TextStyle nesnesi oluşturmak için TextStyle sınıfını kullanarak başlayabiliriz. Aşağıdaki örnek gibi bir TextStyle nesnesi oluşturalım:

Bu kod bloğu, 20 piksel boyutunda kalın siyah bir metin stilini tanımlar. fontWeight özelliği, metnin kalınlığını belirler. Burada, FontWeight.bold ile metnin kalınlığı en yüksek ayara getirilmiştir. Ayrıca, metin rengi de belirtilmiştir.

Şimdi bu metin stilini kullanarak bir metin öğesi oluşturalım:

Bu kod bloğu, “Flutter yazılımı harikadır!” ifadesini myTextStyle nesnesiyle stilize eder. TextStyle nesnesi, metnin stil özelliklerini belirttiğimiz yerdir.

Biraz daha karmaşık bir örnek yapalım ve metin stilini daha ayrıntılı hale getirelim. Aşağıdaki kod bloğu, farklı renklerdeki ve boyutlardaki metinleri içeren bir sütun oluşturur:

Bu kod bloğu, üç farklı metin öğesi oluşturur, her biri farklı bir stil özelliğiyle donatılmıştır. İlk metin normal kalınlıkta ve mavi renklidir, ikinci metin kalın ve kırmızı renklidir, üçüncü metin ise eğik yazı stili ve yeşil renkli olarak belirlenmiştir.

Sonuç olarak, TextStyle, Flutter’da metin stillerinin uygulanması için çok kullanışlı bir araçtır. Bu örneklerin yardımıyla, farklı metin stillerini uygulama konusunda daha fazla fikir edinmiş olabilirsin.

Aşağıdaki örnek, kullanıcı tarafından belirtilen parametrelere göre farklı metin stilleri oluşturur:

Bu kod bloğu, CustomText adlı bir özel widget sınıfı oluşturur. Bu widget, text, fontSize, color, fontWeight ve fontStyle gibi parametreler alır. Bu parametreler, metin stilinin farklı özelliklerinin belirlenmesini sağlar.

Bu özel widget’ı kullanarak farklı metin stilleri oluşturabiliriz:

Bu kod bloğu, CustomText sınıfını kullanarak üç farklı metin öğesi oluşturur. Her biri, farklı bir parametre değeri ile farklı bir metin stilinde gösterilir. Bu, kullanıcıların metin stillerini kolayca özelleştirebileceği ve uygulamamızdaki metinlerin daha çeşitli ve özelleştirilmiş görünmesini sağlar.

Sonuç olarak, TextStyle, Flutter’da metin stilleri oluşturmak için kullanışlı bir araçtır. Parametreler eklemek, metin stillerinin özelleştirilmesini ve uygulamalarda daha çeşitli metin stillerinin kullanılmasını sağlar.

Flutter’da TextStyle kullanarak oluşturabileceğimiz 10 farklı örnek şunlar olabilir:

Başlık metni stilini oluşturma:

Alt başlık metni stilini oluşturma:

Normal metin stilini oluşturma:

İtalik yazı stili oluşturma:

Metin gölgesi ekleyerek yazıyı vurgulama:

Altı çizgili metin stilini oluşturma:

Üstü çizgili metin stilini oluşturma:

Gölgeli metin stilini oluşturma:

Harf büyüklüğünü küçültme:

Çok satırlı metinler için satır yüksekliğini ayarlama:

 

Kategori Featured, Flutter
21.03.2023
85 Okunma

Flutter Custom Font Ekleme

Flutter’da özel font eklemek için aşağıdaki adımları takip edebilirsiniz:

İlk olarak, kullanacağınız özel font dosyasını projenize eklemeniz gerekiyor. Bu dosyayı, “assets/fonts” dizinine kopyalayabilirsiniz.

Daha sonra, “pubspec.yaml” dosyanızı açın ve “fonts” sekmesine gidin. Burada, yeni bir öğe eklemek için aşağıdaki kodu kullanabilirsiniz:

Burada, [font-family-name] özel fontun adını, [font-file-name] ise dosyanın adını belirtir.

Bu adımdan sonra, özel fontu kullanmak için MaterialApp veya TextStyle gibi bir widget kullanabilirsiniz. Örneğin, aşağıdaki gibi TextStyle kullanabilirsiniz:

Bu şekilde, özel fontunuzu Flutter uygulamanıza başarıyla ekleyebilirsiniz.

Kategori Featured, Flutter
16.03.2023
83 Okunma

Flutter Stack Kullanımı

Stack widget’i, diğer widget’ların üstüne konumlandırılmasına olanak tanıyan bir widget’dır. Genellikle Overlay, GridView, ListView veya Row/Column gibi widget’ların içinde kullanılır.

İşte basit bir örnek:

Bu örnekte, Stack widget’i, dört farklı Container widget’ını içerir. Her bir Container widget’ı, farklı bir renk ve farklı bir konumda yer alır. Positioned widget’ı, her bir Container widget’ını belirli bir konuma yerleştirir.

Stack widget’ı, diğer widget’ların üstüne konumlandırılabilmesi nedeniyle çok yönlü bir widget’dır. Örneğin, bir resim veya video oynatıcı widget’ı, Stack widget’ı içinde konumlandırılabilir ve üstüne farklı widget’lar eklenebilir.

Flutter’da Stack widget’ının birçok farklı kullanımı ve özelliği vardır. Umarım bu örnekler size başlangıçta yardımcı olmuştur.

Bir resim widget’ı ve bir metin widget’ını Stack widget’ı içinde konumlandırma:

Bir video oynatıcı widget’ı ve üstünde bir düğme widget’ı Stack widget’ı içinde konumlandırma:

Bir resim widget’ı, bir ikon ve bir metin widget’ını Stack widget’ı içinde konumlandırma:

Bu örnekler, Stack widget’ının nasıl kullanılabileceği konusunda farklı fikirler vermektedir. İhtiyaçlarınıza göre Stack widget’ını kullanarak, farklı widget’ların üst üste konumlandırılmasıyla, çok çeşitli tasarımlar yapabilirsiniz.

Kategori Featured, Flutter
16.03.2023
82 Okunma