FLUTTER İLE API KULLANIMI

Levent
Flutter Students Club

--

Herkese tekrar merhaba. Widgetlarla ilgili yazdığım son yazımdan sonra Flutter konusunda kendimi geliştirmeye devam ettim ve bu ay yazımda sizlere yeni öğrendiğim bir konu olan API ile çalışmayı anlatacağım. Konuya girmeden önce henüz gelişim aşamasında bir geliştirici olarak yazımda fark edeceğiniz hata ve/veya eksiklikleri Twitter adresimden bana ulaşarak bildirirseniz çok memnun olurum. Hazırsanız bu ayki konumuza başlayalım.

Nedir Bu API ?

Gelin ilk önce kısaca API’den bahsedelim. Açılımı Application Programming Interface olan API için uygulamamızın dünyaya açılan kapısı desek yalan olmaz. Uygulamamızı besleyen kaynaklarla uygulamamız arasında, uygulamamızın bağlantılı olduğu diğer platformlar arasında köprü görevi görür. Bunun yanında uygulama ile cihaz donanımızı kullanabilmemizi sağlayan bir etkendir.

Peki Ya JSON ?

JSON’un açılımı JavaScript Object Notationdur. Aslında JavaScript programlama diline dayanır. Ne yani durduk yere JavaScript mi öğreneceğiz ? Buna en azından şimdilik ihtiyacınız yok çünkü JSON sadece JavaScript ile kullanılan bir şey değil aksine kullanımı dilden bağımsızdır. JSON verilerin sunucu tarafından, kullandığımız mobil uygulamalarda veya web sayfalarında, geliştiricinin bu veriyi kullanıcı arayüzüne rahatça yerleştirmesini sağlayan ve bu işlemin tüm dünyada aynı olmasını sağlayan bir standarttır.

JSON örneği

Yukarıda gördüğünüz şey aslında 36.96 enleminde, 122.02 boylamında bulunan bölgenin hava durumunu bize gösteren basit bir JSON formatıdır. İşte kullanıcıyı bu karmaşık yapılarla yalnız bırakmamak için geliştirici yazılım dünyasında standartlaşmış bu formatı işler ve gerekli bilgiyi kullanıcının karşısına çıkartır.

FLUTTER’DA API KULLANIMI

Sıra geldi bu yazının asıl konusuna. Flutter ile bir uygulama geliştirdiniz ama şuanda sadece sizin statik olarak yerleştirdiğiniz bilgiler mevcut ve dışarıyla hiçbir etkileşimi yok. Bir süre sonra geliştirdiğiniz uygulama size sıkıcı gelmeye başlayabilir.

Flutter dokümantasyonlarını incelediğimizde backend bölümünde bize serialization gibi bir kavramdan bahsediliyor ve bunun bir nesneyi String yapısına çevirmek olduğundan bahsediliyor.

Flutter’da iki adet serialization yöntemi mevcuttur. Bunlar arasında doğru ya da yanlış yoktur. Uygulamanız ne kadar basitse Manual serialization kullanmanız işinizi çok daha kolaylaştıracaktır. Karmaşık uygulamalarda ise ikinci yöntemimiz olan Automated serialization kullanmanız daha faydalıdır.

1- Manual serialization:

Bu yöntemde JSON içindeki verileri inline kod olarak ya da bir model oluşturarak elde edeceğiz.

1.a) Inline yöntemde Flutter’ ın kütüphanelerinden dart:convert kütüphanesinden faydalanacağız. Bu kütüphanede bulunan jsonDecode() fonksiyonu verilen String değerini ayrıştırır ve elde edilen JSON nesnesini geri döndürür.

Gelin bu konuyu API hizmeti kullanan basit bir Flutter uygulamasını birlikte yazarak öğrenelim.

Programımızda yazılan kelimeyle ilgili gif barındıran ücretsiz API hizmeti veren web sitemizden faydalanacağız. Sitenin API dokümantasyonunda bize nasıl request atabileceğimiz anlatılmakta. Peki request nedir ? Request API hizmeti aldğımız kaynağa yaptığımız istektir. Yani aslında ben senden şu şu bilgileri istiyorum bana verir misin demekteyiz. İstek attığımız kaynak ise bize bir response döndürür. Kelime anlamından da tahmin edilebileceği gibi response, bulunduğumuz isteğe göre gelen yanıttır. Konumuza dönecek olursak kullanacağımız sayfanın bize verdiği örnek istek "https://g.tenor.com/v1/search?q=excited&key=LIVDSRZULELA&limit=8" şeklinde. Bu ifadeyi tarayıcınızda arattığınızda yazımın başında örnek olarak koyduğum JSON verisine benzer ve çok daha karışık bir response ile karşılaşacaksınız.

Bu karmaşıklığı gidermek adına Chrome tarayıcınızda JSON Viewer adlı eklentiyi kurabilirsiniz. Firefox tarayıcısında ise herhangi bir eklenti kurmadan daha okunaklı halde inceleme yapabilirsiniz. Ya da Google’ da JSON formatter yazarak elde ettiğiniz JSON verisini daha okunaklı hale getiren sitelerden yardım alabilirsiniz. Bunların hiçbiri size uymazsa Postman adlı uygulama size çok yardımcı olacaktır. Uygulamamıza dönecek olursak;

Uygulama kodlarımızın en başında normalden farklı olarak Flutter’ ın http ve dart:convert kütüphanesini ekliyoruz. İkinci satırda as anahtar kelimesi ile yaptığımız şeyin ne olduğunu bilmiyorsak burayı inceleyebiliriz.

HomePage adlı statefull widgetımızın başında kullanacağımız değişkenleri tanımladık. gifSubject değişkeni daha sonra dinamik olarak istediğimiz konudaki gifleri çekebilmemizi sağlayacak. Program başladığında kullanıcının welcome konulu giflerle karşılanması için değişkeni ‘welcome’ değerine eşitledik. gifUrls ise API’ ya istek attıktan sonra bize dönecek olan giflerin urllerini saklayacağımız bir list. allGif listi ise daha sonra ekranda göstereceğimiz ve her biri bir gif barındıracak widgetların saklanacağı değişkenimiz. parsedResponse değişkenini ise izninizle yeri geldiğinde sizlere açıklayayım.

Değişkenlerimizi sırayla tanımladıktan sonra sıra API ile çalışacağımız zaman bilmemiz gereken Future konusuna geldi. Future bizlere yanında async ve await konularını da getirmektedir. Bu üç kavram aslında asynchronous (asenkron) programramlama altında incelenmektedir.

Asenkron programlama, uygulamamız ağ üzerinden veri alırken, veritabanı üzerinde işlem yaparken veya dosya içinden veri okurken istenilen veri gelmeden ya da gönderilmeden işlem yapılmasını engeller. Bu da bizim farklı hatalarla karşılaşmamızı önler. Örnek programımız üzerinden konuşacak olursak; happy kelimesiyle ilgili gifleri arattık diyelim. API’ dan beklenen gifler gelmeden bu gifleri ekrana koymaya çalışırsak kullanıcı istemediğmiz hatalarla karşılaşacaktır. Asenkron programlama sayesinde önce API’ ya istek atılır. Sonraki işlemler yapılmadan önce istek üzerine gelecek cevap beklenir. Daha sonra gelen cevaba göre işlemler devam ettirilir.

Konumuza Future ile devam edelim. Future geliştiriciye asenkron programlama sırasında yapılacak işlemin sonucunu döndürür. Gözünüz korkmasın. Kullanımı sıradan fonksiyonlara çok benzemektedir.

Senkron Programlama
Future Örneği

Flutter dokümantasyonlarında bulunan yukarıdaki örneklerin ilki zaten bilmekte olduğumuz senkron programlama örneği. createOrderMessage() fonksiyonu çağrıldığında ‘Your order is: $order’ ifadesini döndürecek ve fonksiyon gövdesinde return tipi String olduğu için String olarak belirtilmiş. Alttaki örnekte ise asenkron programlamada Future kullanımını görmekteyiz. Asenkron programlama sırasında bize cevap gelene kadar Future döndürülür. Örnekteki <String> ifadesi kullanılacak Futureın ileride String değerinde olacağını belirtmektedir. Aynı normal fonksiyonun gövdesinde belirtilen String değeri gibi. Gelelim async ve await anahtar kelimelerine…

async ve await anahtar sözcükleri, asenkron işlevleri tanımlamanın ve sonuçlarını kullanmanın bildirimsel bir yolunu sağlar.

Flutter dokümantasyonunda bu iki kelime kısaca bu şekilde açıklanmış. Bununla da yetinilmeyip kısa bir de örnek verilmiş.

async kullanım örneği

Örnekte görüldüğü gibi async anahtar kelimesi fonskiyonun gövdesinde, fonksiyon tanımından önce kullanılmaktadır.

await kullanım örneği

Bu örnekte de await kullanım örneği görülmekte. Bu şekilde asenkron programlamada Future’ın tamamlanmasını bekleyen bir komut elde etmiş olduk.

Tekrar örnek uygulamamıza dönelim. giffApp2.dart adlı örnekte ikinci satırda Uri.parse() fonksiyonunu kullanarak url değişkenimize convert:dart kütüphanesinden gelen get() fonksiyonunun kabul edeceği Uri nesnemizi atadık. Bu nesne ile get() fonksiyonunu çağırdıktan sonra response adlı değişkenimize https://g.tenor.com/v1/search?q=excited&key=LIVDSRZULELA&limit=8 isteği atıldığında bu linke istek atmış oluruz. Daha sonra elde ettiğimiz değişkeni ile jsonDecode() fonksiyonunu çağırarak get() fonksiyonu ile elde ettiğimiz Json nesnesini ayrıştırarak bize döndürür. Dönen değeri parsedResponse değişkenine atıyoruz. Bu kadar şeyi yaptık peki ne elde ettik ?

Hadi gelin print('parsedResponse: $parsedResponse') komutu ile bu kadar işlemden sonra elimize ne geçmiş görelim.

parsedResponse değişken değeri

Yukarıdaki görseli detaylı incelerseniz istek attığımız linkte bildirdiğimiz excited kelimesine göre bize sekiz adet gif adresinin bulunduğu bir map türünde bir değişken geldi. Sıra bu değişkeni tam anlamıyla parça parça yapıp bu sekiz adet linki uygulamamızda kullanmak. giffApp2.dart adlı örneğin on birinci satırında parsedResponse['result'][i]['media'][0]['gif']['url'] ifadesinde for döngüsü ile tüm linkleri alıp en başta tanımladığımız gifUrls adlı list değişkenine ekliyoruz. Daha sonra url adlı bir değişken alan ve bizim tanımladığımız Gif adlı widgeta bu urli gönderip oluşturduğumuz widgetı yine en başta tanımladığımız ve widget türünde değişken alan allGif adlı liste ekliyoruz. Kendi tanımladığımız Gif adlı widgetın kodlarını aşağıda paylaşıyorum.

Gif Widgetı

Bu widgetı tanımlarken url adlı değişken alacak şekilde tanımladık ve constructor (yapıcı fonksiyon) ile bu değişkeni kullanıp widget oluşturduk. Gelen url değişkenini Image.network() widgetı ile kullanıp elde ettiğimiz url leri kullanıcıya görsel bir şekilde sunduk.

Verimizi Manual serialization yöntemlerinden olan dart:convert kütüphanesini kullanarak API’ dan çektik ve gelen bilgileri işledik. Dilerseniz bu işlemi diğer bir Manual seralization yöntemi olan model class kullanarak da tekrarlayalım.

1.b) Manual serialization yöntemlerinden ikincisi olan model class kullanımında inline kod kullanımından daha düzenli bir kod yapısı elde ederiz. Gelin yine adım adım uygulama kodlarında inceleme yapalım.

Yukarıda gördüğünüz class tam olarak uygulamamızda kullanacağımız model. İsimlendirme tamamen sizin keyfinize kalmış durumdadır. Gelin neler yapıldığına bakalım. İlk önce classımızın değişkenleri tanımlandı. Bunu yaparken tamamiyle kullancağımız API’ ya bağımlı durumdayız. Kullandığımız API bize içinde results adlı bir List ve next adlı bir String değeri gönderdiği için biz de modelimiz içinde bunları tanımladık. Daha sonra sıra bu classımıza bir named constructor yazma vakti geldi. Biz isim olarak konuyla alakası olması adına fromJson ismini verdik. Bu constructor Map bir tipinde bir değişken alacak ve bu değişkenin içindeki results değeri nesnemizin resutls değerine, değişken içindeki next değeri de nesnemizin next değişkenine atanacak (this anahtar kelimesi). Yazının başlarında giffApp.dart ve gifApp2.dart isimli kod örneklerinde yaptığımız değişikliği aşağıda görebiliriz.

Sizlerin de görebileceği gibi değişkenlerimize bir yenisi daha eklendi. O da giffApp3.dart adlı kodda oluşturduğumuz classtan oluşturulan gifModel adlı değişken. Manual serialization yöntemlerinden ilkinde bütün yükü parsedResponse adlı değişkenimize yüklemiştik şimdi ise görüyoruz ki bu değişkeni GifModel adlı classın sahip olduğu fromJson adlı constructorun bizden istediği Map değişkeni yerine koyuyoruz. Modeli açıklarken de anlattığım gibi parsedResponse değeri içindeki results gifModel adlı nesnenin result değerine ve parsedResponse değişkeni içindeki next de gifModel nesnesinin next değişkenine eşitlendi. Son olarak da for döngüsü içinde gifModel adlı nesnemizin özelliklerine sırayla erişerek onları daha önce yaptığımız gibi Listlerimizin içine ekledik ve uygulamamızın ilk baştaki gibi çalışmasını sağladık.

Bu yazımda sizlere Flutter’da Manual Serialization yöntemlerini anlatmaya çalıştım. Ben de sizler gibi sürekli olarak Flutter konusunda kendimi geliştirmeye çalışıyorum. En yakın zamanda kendimi daha çok geliştirip sizlerin karşısına Automated Serialization yöntemiyle de çıkmak isterim.

Buraya kadar okuduğunuz ve eklemek istediklerinizi bana bildirdiğiniz için şimdiden çok teşekkür ederim. Bir sonraki yazımda görüşmek üzere. Kendinize iyi bakın…

Proje Kodlarının Linki

--

--