Flutter and Widget Concept

 


When learning Flutter, I think the first thing to do to grasp its general logic is to learn about widgets and their hierarchy. So in this article I wanted to talk about widgets and the widget tree in Flutter.

What is a Widget?

Widgets are the basic building blocks for creating the user interface in Flutter applications. Everything is a widget. A text box, a button, an image, even icons. Everything is represented as a widget in Flutter.

Widget Types

There are two types of widgets used in Flutter.

1. Stateless Widget

Stateless: Does not contain any state. That is, once created, the information it contains cannot be changed. The widget’s appearance depends on its initial properties and the widget itself does not change unless these properties change.

Build Method Only: Usually contains only the “build” method. This method specifies how the widget will be displayed.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter and Widget Concept'),
),
body: Center(
child: Text('Stateless Widget'),
),
),
);
}
}

In the example above, the text placed in appBar and body is written as immutable, so there is no state change here. StatelessWidget should be preferred because it does not need to be built again and again every time the application is refreshed.

2. Stateful Widget

Stateful: It can track the state thanks to a “State” object it contains. That is, after the widget is created, its state can change and these state changes are used to update the UI.

State Class: Stateful Widget is a class, but the actual state is contained in a separate “State” class. The “State” class contains the state of the widget and when it is updated, the “build” method is called again.

class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Count Value: $_counter'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increase'),
),
],
),
),
),
);
}
}

In this example, a State management is required in CounterApp. There is a counter operation and the value of this counter is initially displayed on the screen and when the “Increase” button is clicked, the value of the counter increases. In this example, the _CounterAppState class keeps track of state changes and displays the current value of the counter on the screen. This means that there are changes in the background and UI and this piece of code needs to be rebuilt every time the application is refreshed. This is why StatefulWidget should be used.

At the beginning of my learning process, while I was frequently making inquiries such as what is state, what does it mean to build, I thought the following. If we can’t decide which part of the application to use stateful and which part to use stateless, we can use stateful. Because stateless can’t do the operations of stateful, but stateful does everything :) You may have thought like this too. However, performance issues arise here.

Recommendations for Use

  • If the appearance of a widget will not change after it is created and there is no need for status tracking, it may be more appropriate to use “Stateless Widget”.
  • If a widget’s appearance will change depending on the data it contains or will change as a result of user interactions, it makes sense to use “Stateful Widget”.

Ideally, widgets should be as stateless as possible, because stateless widgets are usually simpler, lighter and more performant. Stateful one should only be used when necessary.

Widget Tree

In Flutter, widgets are organized in a tree structure, creating a hierarchy.

- MaterialApp
- Scaffold
- AppBar
- Text
- Center
- Column
- Text
- SizedBox
- ElevatedButton

The widgets of the simple counter application above form a tree structure like this. This hierarchy shows how the widgets are embedded and related to each other. This is important for understanding how widgets are placed and interact with each other.

In conclusion, the Widget tree in Flutter is a fundamental concept used to build the interface of our application. Widgets are organized in a hierarchy and this tree structure determines the look and behavior of our app. I hope I have explained it in a simple way, I hope to be useful.

Thank you.

Selin.

Flutter ve Widget Kavramı

 


Flutter öğrenirken genel mantığını kavramak için yapılacak ilk şey, sanırım, widget’ları ve bunların hiyerarşisini öğrenmek. Ben de bu yazımda Flutter’da widget’lar ve widget ağacından bahsetmek istedim.

Widget Nedir?

Widget’lar, Flutter uygulamalarında kullanıcı arayüzünü oluşturmak için temel yapı taşlarıdır. Her şey bir widget’tir. Bir metin kutusu da, bir buton da, bir resim de, hatta ikonlar bile. Flutter’da her şey bir widget olarak temsil edilir.

Widget Türleri

Flutter’da kullanılan iki tür widget bulunur.

StatelessWidget:

  • Durumsuz (Stateless): İçinde durum (state) barındırmaz. Yani, bir kez oluşturulduktan sonra içerdiği bilgiler değiştirilemez. Widget'ın görünümü, başlangıçtaki özelliklerine bağlıdır ve bu özellikler değişmedikçe widget kendisi değişmez.
  • Sadece Build Metodu: Genellikle sadece “build” metodunu içerir. Bu metod, widget'ın nasıl görüntüleneceğini belirtir.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter ve Widget Kavramı'),
),
body: Center(
child: Text('Stateless Widget'),
),
),
);
}
}

Yukarıdaki örnekte appBar ve body içerisine yerleştirilen metinler değişmez olarak yazıldığından, burada bir durum değişimi yoktur. Uygulama her yenilendiğinde tekrar tekrar “build” edilmesine gerek olmadığından StatelessWidget tercih edilmelidir.

StatefulWidget:

  • Durum İçerir (Stateful): İçerdiği bir “State” nesnesi sayesinde durumu takip edebilir. Yani, widget oluşturulduktan sonra durumu değişebilir ve bu durum değişiklikleri UI'ı güncellemek için kullanılır.
  • State Sınıfı: Stateful Widget bir sınıftır, ancak asıl durum (state) bu sınıftan ayrı bir “State” sınıfında bulunur. “State” sınıfı, widget'ın durumunu içerir ve güncellendiğinde “build” metodu tekrar çağrılır.
class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Sayac Uygulaması'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Sayac Değeri: $_counter'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Arttır'),
),
],
),
),
),
);
}
}

Bu örnekte ise CounterApp içerisinde bir State yönetimi gerekir. Burada bir sayaç işlemi mevcut ve bu sayacın değeri başlangıçta ekranda gösterilir ve “Arttır” butonuna tıklandığında sayacın değeri artar. Bu örnekte, _CounterAppState sınıfı durum değişikliklerini takip eder ve sayacın güncel değerini ekranda gösterir. Yani arka planda ve UI’da değişiklik mevcuttur ve uygulama her yenilendiğinde bu kod parçasının yeniden build edilmesi gerekir. Bu sebepten StatefulWidget kullanılması gerekir.

Öğrenim sürecimin başlarında state nedir, build etmek ne demektir gibi sorgulamaları sıkça yaparken şunu düşünmüştüm. Uygulamanın hangi kısmında stateful hangisinde stateless kullanacağımıza karar veremediysek stateful kullanıp geçebiliriz. Çünkü stateless stateful’un işlemlerini yapamıyor ama stateful her işi görür. :) Siz de böyle düşünmüş olabilirsiniz. Ancak burada karşımıza performans sorunları çıkıyor.

Kullanım Tavsiyeleri:

  • Eğer bir widget’ın görünümü, oluşturulduktan sonra değişmeyecekse ve durum takibine ihtiyaç duyulmuyorsa, “Stateless Widget” kullanmak daha uygun olabilir.
  • Eğer bir widget’ın görünümü, içerdiği verilere bağlı olarak değişecekse veya kullanıcı etkileşimleri sonucunda değişiklik gösterecekse, “Stateful Widget” kullanmak mantıklıdır.

İdeal durumda, widget’lar mümkün olduğunca durumsuz (stateless) olmalıdır, çünkü durumsuz widget’lar genellikle daha basit, hafif ve performanslıdır. Stateful, sadece gerekli olduğunda kullanılmalıdır.

Widget Ağacı

Flutter’da, widget’lar bir hiyerarşi oluşturarak bir ağaç yapısında düzenlenir.

- MaterialApp
- Scaffold
- AppBar
- Text
- Center
- Column
- Text
- SizedBox
- ElevatedButton

Yukarıdaki basit sayaç uygulamasının widget’ları şu şekilde bir ağaç yapısı oluşturur. Bu hiyerarşi, widget’ların nasıl gömülü olduğunu ve birbirleriyle ilişkili olduklarını gösterir. Bu, widget’ların nasıl yerleştirildiğini ve birbirleriyle etkileşime girdiğini anlamak için önemlidir.

Sonuç olarak, Flutter’da Widget ağacı, uygulamamızın arayüzünü oluşturmak için kullanılan temel bir kavram. Widget’lar, bir hiyerarşi içinde düzenleniyor ve bu ağaç yapısı, uygulamamızın görünümünü ve davranışını belirliyor. Umarım basitçe anlatabilmişimdir, faydalı olmayı umuyorum.

Sevgiler.

Selin.

Joyful Learning: Flash Cards

 

🚀 Great News! A brand new start! 🚀

Hello Medium family! I have exciting news for you! Today, I released my new flashcards app for kids on Google Play Store! 🌟✨✨

This app is designed to help children learn in a fun way. Thanks to my application, which is full of colorful, interactive and educational cards, children will both have a pleasant time and be involved in the learning process. 📚🎉

📲 It is currently available for download on the Google Play Store and you can let your kids explore!

🔗 https://play.google.com/store/apps/details?id=com.cemnamak.flash_cards

For now, the app only supports Turkish language, but I will add English language support very soon. It is important for me to contribute to the education of children in both languages.

This app is a first for me and the experience I gained during this process has encouraged me to start more similar projects in the future. I can’t wait to come up with more educational content in new projects 🚀 🚀

Your support is invaluable to me in this exciting journey. You can help me bring this app to a wider audience by sharing it with your family members, friends and everyone around you.

Thank you in advance for this support 🙏💙

Joyful Learning: Flash Cards

 

🚀 Harika Haberler! Yepyeni bir başlangıç! 🚀

Merhaba Medium ailesi! Sizlere heyecan verici bir haberim var! Bugün, çocuklara yönelik hazırladığım yeni flashcards uygulamamı Google Play Store’da yayınladım! 🌟✨

Bu uygulama, çocukların eğlenceli bir şekilde öğrenmelerini sağlamak amacıyla tasarlandı. Renkli, etkileşimli ve eğitici kartlarla dolu olan uygulamam sayesinde, çocuklar hem keyifli zaman geçirecekler hem de öğrenme sürecine dahil olacaklar. 📚🎉

📲 Şu anda Google Play Store’dan indirilebilir ve çocuklarınızın keşfe çıkmasına izin verebilirsiniz!

🔗 https://play.google.com/store/apps/details?id=com.cemnamak.flash_cards

Şu an için uygulama yalnızca Türkçe dil desteği sunuyor, ancak çok yakında İngilizce dil desteği de ekleyeceğim. Her iki dilde çocukların eğitimine katkıda bulunmak benim için önemli.

Bu uygulama, benim için bir ilk ve bu süreçte edindiğim deneyim, gelecekte daha fazla benzer projeye başlamam için beni kamçıladı. Yeni projelerde daha fazla eğitici içerikle karşınıza çıkmak için sabırsızlanıyorum! 🚀

Bu heyecan verici yolculukta sizlerin destekleri benim için çok değerli. Aile üyelerinizle, arkadaşlarınızla ve çevrenizdeki herkesle paylaşarak, bu uygulamayı daha geniş bir kitleye ulaştırmama yardımcı olabilirsiniz.

Bu destek için şimdiden teşekkür ederim! 🙏💙

The “context” issue in Flutter

 


It’s been about 8 months since I started working with Flutter, I can say that I didn’t have much difficulty in understanding the general writing principles and widget tree.

The reason why I preferred Flutter was that it is becoming increasingly popular and can be output on different platforms with the same code. Indeed, I was able to develop tiny applications in a short time and this motivated me even more.

But there is a context issue that I have to say that I used it by heart at first :) Fortunately, as I worked on it and used it in different applications and widget structures, I understood its logic and decided to write about it first because I thought that there might be people like me who have difficulties.

What is context?

The first thing we need to know about context is that it is present in the widget tree in our application and it is a context as in the dictionary sense. Within this context, it controls the current state, location and interaction with other widgets. In simpler terms, it refers to the context in which a widget exists.

What is BuildContext?

In order to better understand what a context is, it is very important to understand the BuildContext class it depends on.

BuildContext points to a point in the widget tree. This point contains the widget’s location, theme information and other context information. We use this structure to share information and state between widgets, use navigator methods, access theme information, and so on. This makes our application more modular, flexible and maintainable.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}

The code above is the first code that is automatically generated for us when creating a project in Flutter. Here we see that BuildContext is used as the parameter of the build method. Here “context” represents the context information from the place that calls this method.

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Example of BuildContext'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 'context' can be used here
showSnackBar(context);
},
child: Text('Show Snackbar'),
),
),
);
}

In this example, we show a snackbar using BuildContext. By passing the context to the showSnackBar method, we make the method use the current context in the widget tree.

Therefore, SnackBar detects where it is located in the widget tree, what its context is, where it is triggered from, and behaves accordingly. So shoxSnackBar gets its context from the context of the build method. That context, this context :).

As a result, making our Flutter application more sustainable and flexible depends on proper communication between widgets and we can use this very easily with the BuildContext structure.

I hope I was able to clear up some of the confusion and helped you a little bit.

Thank you.

Selin.

Flutter’da “context” Meselesi

 


Flutter çalışmaya başlayalı yaklaşık 8 ay kadar oldu, genel yazım prensiplerini, widget ağacını anlamakta pek zorlanmadım diyebilirim.

Flutter’ı tercih etmekteki sebebim ise giderek popüler olması ve aynı kodla farklı platformlarda çıktı alınabiliyor olmasıydı. Gerçekten de kısa sürede minik de olsa uygulamalar geliştirebildim ve bu beni daha da motive etti.

Fakat bir context meselesi var ki, bunu ilk başlarda ezbere kullandığımı söylemezsem olmaz :) Neyse ki üzerinde çalıştıkça, farklı uygulamalar ve widget yapılarında kullandıkça mantığını kavradım ve benim gibi zorlananlar olabileceğini düşündüğüm için ilk olarak bunun üzerine yazmaya karar verdim.

Context nedir?

context ile ilgili ilk bilmemiz gereken şey, uygulamamızdaki widget ağacında bulunması ve sözlük anlamında olduğu gibi bir bağlam. Bu bağlam içerisinde mevcut durumu, konumu ve diğer widget’lar ile etkileşimi kontrol ediyor. Daha basit anlatımla bir widget’in içinde bulunduğu bağlamı ifade ediyor.

BuildContext nedir?

context’in ne olduğunu daha iyi anlayabilmek için bağlı bulunduğu BuildContext sınıfını anlamak çok önemli.

BuildContext widget ağacında bir noktayı işaret eder. Bu noktada, widget’ın yeri, tema bilgileri ve diğer bağlam bilgileri de yer alır. Biz bu yapıyı kullanarak widget’lar arasındaki bilgi ve durumu paylaşır, navigator metodlarını kullanır, tema bilgilerine erişiriz, ve bunun gibi daha bir çok şey. Böylelikle uygulamamız daha modüler, esnek ve sürdürülebilir hale gelir.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}

Yukarıdaki kod, Flutter’da proje oluştururken bizim için otomatik olarak oluşturulan ilk kod. Burada build metodunun parametresi olarak BuildContext kullanıldığını görüyoruz. Burada “context” bu metodu çağıran yerden gelen bağlam bilgisini temsil ediyor.

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BuildContext Örneği'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 'context' burada kullanılabilir
showSnackBar(context);
},
child: Text('Snackbar Göster'),
),
),
);
}

Bu örnekte, BuildContext’i kullanarak bir snackbar gösteriyoruz. showSnackBar metoduna context’i geçerek, metodun widget ağacındaki mevcut bağlamı kullanmasını sağlıyoruz.

Dolayısıyla SnackBar widget ağacının neresinde konumlandığını, bağlamının ne olduğunu, nereden tetiklendiğini bu context sayesinde tespit ederek buna göre davranıyor. Yani shoxSnackBar context’ini build metodunun context’inden alıyor. O context, bu context :).

Sonuç olarak geliştirdiğimiz Flutter uygulamamızın daha sürdürülebilir ve esnek olabilmesi widget’lar arasındaki düzgün iletişime bağlı ve bunu da BuildContext yapısıyla çok kolay bir şekilde kullanabiliyoruz.

Umarım mevcut kafa karışıklıklarını biraz olsun giderebilmişimdir ve faydam dokunmuştur.

Sevgiler.

Selin.