Flutter’da Temiz Routing

Mirkan
Flutter İzmir
Published in
3 min readJun 23, 2019

Bu yazımda Flutter’a başladığımdan beri navigasyon ile ilgili işlerde çözüm sürecimin nasıl geliştiğini ve evrildiğini anlatacağım. Aynı zamanda şuan kullandığım en temiz halini de görmüş olacaksınız.

Giriş

Android tarafında Activity, iOS tarafında ViewController bizim bu yazıda bahsettiğimiz route’dur. Flutter’da ise bunlar screens ve pages, yani sayfalar route’dur ve bunlar widget’tır.

Klasik Navigator.push()

Yeni bir route’a geçmek için Navigator’ı kullanabilirsiniz. Navigator.push() metodu, yeni bir route’u Navigator tarafından kontrol edilen bir yığın’a(stack) atıyor. Navigator.push fonksiyonu context ve route’u parametre olarak alıyor.

Peki route’u nerden bulabiliriz ve bu metoda atabiliriz?

Kendi route’unuzu yaratabilirsiniz ya da MaterialPageRoute kullanabilirsiniz. MaterialPageRoute aşağıda olduğu gibi bir builder fonksiyonu istiyor ve bu fonksiyonda context’i parametre alıyor. Geri kalanı ise kendi yazdığınız widget. Geri gelmek için yani stack’teki route’u atmak için Navigator.pop() metodunu kullanabilirsiniz.

Eğer yeni sayfada Scaffold ve AppBar kullandıysanız, AppBar’ınızdaki geri tuşu ile geri gelebilirsiniz. Ekstradan kendiniz pop yazmanıza ve sol üstte bir ikonun onPressed metoduna vermenize gerek yok.

Şimdi hemen bir Flutter projesi açalım, biraz da main.dart’ı temizleyelim.

main.dart

lib klasörü altına screens diye bir klasör açıp 2 tane de sayfamızı orda yazalım.

Anasayfada bir butonumuz var ve diğer sayfaya az önce öğrendiğimiz Navigator.push metodu ile geçmemizi sağlıyor.

Anasayfa

İkinci sayfa, sadece bir Text widget gösteriyoruz.

İkinci sayfa

Peki her yerde Navigator.push() mu kullanacağız?

Named Routes Olayı

Aynı route’u uygulamanın birçok yerinde kullanmamız gerekebilir. Bunun için önce route’ları tanımlıyoruz. main.dart dosyamızdaki MaterialApp’in içinde bir nevi route tablosu yapıyoruz, *12. satır. Bu bir map veri yapısı ve solda key olarak String tipinde route’ların isimleri, sağ tarafta ise route’ları yaratmak için metodlar bulunuyor. onUnknownRoute constructor parametresine ise RouteSettings alıp route yaratan bir fonksiyon yazıyoruz, eğer tanımladığımız route’lar dışında bir route gelirse burda yarattığımız route’a gitsin diye. Bu route’ta sadece ekranda “Birşeyler ters gitti” yazan bir sayfadan ibaret.

Anasayfayı da değiştiriyorum çünkü artık Navigator.push() yerine Navigator.pushNamed() kullanacağız. Bir butonda tanımlamadığımız bir route’u göndereceğim, diğerinde ise SecondScreen’i. Bir sayfada birden çok FloatingActionButton olduğunda Hero animasyonlarıyla ilgili bir hata alırsınız, bunun için FAB’lara heroTag’i veriyorum. Yazının altında değineceğim bu konuyada.

Şuan her yerde Navigator.push() yapma olayından kurtulduk ve route’larımız baştan tanımlı oldu. Ayrıca bir şekilde tanımlanmamış route’a düşerse kullanıcımız, farklı bir sayfa da gösterebiliyoruz. Ama bu yaklaşımı da daha temiz bir hala getirme şansımız var.

onGenerateRoute Kullanımı

Fark ettiyseniz bir önceki örnekte, basit olmasına rağmen MaterialApp biraz şişmişti. Burayı biraz rahatlatabiliriz. Bunun için bir route tablosu oluşturmak yerine, MaterialApp’in onGenerateRoute parametresine bir metod vereceğim. Ama önce bu metodu yazalım.

router.dart isimli bir dosya açıyorum. Router class’ı yaratıp metodu yazıyorum. Bu static bir method, yani Router class’ımdan bir obje yaratmadan da kullanabilirim. Bu metod RouteSettings alıyor ve Route döndürüyor. RouteSettings’in name’ine bakıp ona göre MaterialPageRoute veriyor. Bir önceki örnekteki onUnknownRoute’da yaptığımız gibi, burda da switch-case’in default kısmında kullanıcıyı Text widget’tan ibaret bir sayfaya yolluyoruz. Route isimleri ise constant, bunun sebebi ise yanlış yazmanın önüne geçmek.

main.dart’taki MaterialApp widgetımız küçüldü. Tabi bu homeRoute constant’ını burdada kullandığımız için, router.dart’ın altındaki constantları ayrı bir constants.dart dosyasına taşıyabiliriz. onGenerateRoute parametresine az önce yazdığımzı statik metodu veriyoruz, initialRoute’a ise başlangıçta görmek istediğimiz route’u yani anasayfamızı veriyoruz.

Ve böylece Flutter’da Routing işini tertemiz olarak halletmiş oluyoruz.

Bonus: FloatingActionButton ve heroTag

Hero animasyonları, iki ayrı sayfada fakat farklı konumda bulunan bir widget’ın, bu iki yere güzelce geçmesini veya uçmasını sağlıyor. Hero Tag’leri ise bu Hero widget’larını tanımlamak için olan eşsiz etiketler(tag).

İki ayrı sayfada ve farklı konumda mı? Bizim butonlar için bu pek geçerli değil gibi.

FloatingActionButton’lar kendinden Hero Widget içeriyor ve heroTag verilmezse varsayılan bir tag kullanıyor. Flutter bunlara aynı tag’i veriyor ve hata alıyorsunuz. Animasyon istemiyorsanız null verebilirsiniz.

Sorularınızı Twitter @mirkancal ve linkedin üzerinden yazabilirsiniz, sağlıcakla kalın.

Diğer yazılarıma da göz atabilirsiniz.
Flutter Web uygulamasını Peanut ile Github Pages’e Dağıtma
Flutter Uygulama Mimarisi: BLoC
Flutter’da SVG Kullanımı

--

--