Day 16: The Widget Tree & Stateless Widgets

Build your first custom Flutter widget today! Deep dive into StatelessWidgets, the Widget Tree hierarchy, and performance optimization with const.

ရှေ့ရက်တွေမှာ Dart အကြောင်းတွေ လေ့လာတာလဲ တော်တော် ခရီးရောက်ပြီဆိုတော့ ဒီနေ့တော့ Flutter ပိုင်းကို စပြီးတော့ ဆွေးနွေးကြရအောင်ပါ။ အခုထိအတူ လေ့လာခဲ့ကြတဲ့သူတွေ အားလုံးကိုလဲ အများကြီး ကျေးဇူးတင်ပါတယ်။

Flutter ဆိုတာတော့ Google ကနေ Dart Programming Language ပေါ်အခြေခံပြီး ပြုလုပ်ထားတဲ့ UI Toolkit တခုပဲ ဖြစ်ပါတယ်။ ဒီတော့ Flutter app တွေ ရေးကြတဲ့အခါ Dart programming language ကို သိထား နားလည်ထားတယ်ဆိုရင် production ready ဖြစ်တဲ့ app တွေကို အလွယ်တကူ ရေးသွားနိုင်မှာပဲ ဖြစ်ပါတယ်။

Flutter မှာတော့ "Everything is a Widget" လို့ပြောကြတာ ကြားဖူးကြမယ် ထင်ပါတယ်။ Widget ဆိုတာကတော့ UI တွေ တည်ဆောက်တဲ့ block တုံးတွေလို့ မြင်ကြည့်လို့ ရပါတယ်။

ပုံမှာပြထားသလိုပဲ flutter app တွေမှာ ui တွေကို widget တွေနဲ့ ဆောက်ထားတာပဲ ဖြစ်ပါတယ်။ ဒီတော့ ဒီလို widget တွေ အဆင့်ဆင့် တည်ဆောက်ထားတာကို widget tree လို့ခေါ်ပါတယ်။

ဒါကို သေချာလေးမြင်သွားအောင် flutter app တခု create လုပ်ပြီး ကြည့်ကြည့်ကြတာပေါ့။ VS Code မှာ new flutter project တခုဆောက်လိုက်ပါမယ်။

ဒီထဲမှာတော့ default option တွေပဲ ရွေးလိုက်တာဖြစ်တဲ့အတွက် android, ios, linux, macos, web, windows platform တွေ အကုန်ပါလာပါတယ်။ ဒါတွေကိုတော့ လောလောဆယ် ဒီအတိုင်း ထားထားလိုက်ပါမယ်။ ပြီးရင်တော့ emulator/simulator တခုခုကို ဖွင့်လိုက်ပါမယ်။

ပြီးရင်တော့ flutter run ဆိုတာကို terminal ကို ရိုက်လိုက်ပါမယ်။ ခဏစောင့်လိုက်ရင် app ကို build လုပ်ပြီး counter app ကို ရမှာပဲ ဖြစ်ပါတယ်။ ဒါတွေကို day 1 မှာ အသေးစိတ် ပြောခဲ့တာဆိုတော မရှင်းတာရှိရင် သွားရောက်ကြည့်ကြည့်လို့ရပါတယ်။

Day 1: The Setup & “The Run”
Transform your computer into a professional Flutter development workstation and run your first app on a device!

Widget Tree

App run နေတဲ့အချိန် terminal မှာ အခုလိုမျိုး မြင်နေရမှာပဲ ဖြစ်ပါတယ်။

ဒီမှာမြင်နေရတဲ့ "A Dart VM Service on ..." ဆိုပြီးပြထားတဲ့ link ကို browser မှာ ဖွင့်လိုက်ရင် Flutter Dev Tools ပွင့်လာမှာပဲ ဖြစ်ပါတယ်။ ပွင့်လာပြီဆို "Flutter Inspector" ဆိုတဲ့ tab ကို ရွေးလိုက်ပါမယ်။ ဒါဆိုရင်တော့ အောက်မှာပြထားသလို မြင်နေရမှာပဲ ဖြစ်ပါတယ်။

အခု ဒီမှာ မြင်နေရာ widget tree ပဲ ဖြစ်ပါတယ်။ အခုလက်ရှိ app ရဲ့ အဆင့်ဆင့် တည်ဆောက်ပုံကို ပြပေးထားတာပဲ ဖြစ်ပါတယ်။ အပေါ်မှာ ပြထားတဲ့ screenshot နဲ့ဖြစ်ဖြစ်၊ လက်ရှိ ကိုယ် run နေတဲ့ app နဲ့ပဲ ဖြစ်ဖြစ် ဘေးတိုက်ယှဥ်ကြည့်လို့ရပါတယ်။

ဒီတော့ Flutter မှာ UI တည်ဆောက်တဲ့အခါ widget တွေသုံးပြီး tree ပုံစံလိုမျိုး structure နဲ့ UI components တွေကို render လုပ်ပေးပါတယ်။

Widgets

အပေါ်မှာ widget ဆိုပြီး ခဏခဏပြောနေတော့ widget ဆိုတာဘာလဲ ကြည့်ကြည့်ရအောင်ပါ။

Text(
  'Hello World',
  style: TextStyle(fontSize: 24),
)

အပေါ်မှာ ပြထားတာကတော့ Text Widget တခုပဲ ဖြစ်ပါတယ်။ သူ့ကိုတော့ UI မှာ စာတွေ ပြချင်တဲ့အခါ အသုံးပြုနိုင်ပါတယ်။ style ဆိုတာကတော့ ပေါ်လာတဲ့ စာကိုမှ ဘယ်လို size, အရောင်, font စသဖြင့် customize လုပ်ချင်တဲ့အခါ သုံးနိုင်ပါတယ်။ ဘာမှ မထည့်ပေးဘူးဆိုရင်တော့ flutter က default သတ်မှတ်ထားတဲ့ design system အတိုင်း ပြပေးနေမှာပါ။ Text မဟုတ်ဘဲ တခြား component တွေ ပြချင်တယ်ဆိုရင်လဲ Flutter Widget Catalog ထဲမှာ သွားပြီး ရှာကြည့်လို့ရပါတယ်။

Basic widgets
A catalog of Flutter’s basic widgets. Widgets to know before building your first Flutter app.

အပေါ်မှာ တည်ဆောက်ထားတဲ့ counter app ရဲ့ code ကို သေချာကြည့်မယ်ဆို အခုလိုမျိုး အဆင့်ဆင့် widget tree ကို တွေ့ရမှာပဲ ဖြစ်ပါတယ်။

MaterialApp                     // Level 1: The Root
└── Scaffold                    // Level 2: The Structure
    ├── AppBar                  // Level 3: Top Bar
    │   └── Text                // Level 4: Title
    ├── Body                    // Level 3: Main Content
    │   └── Center              // Level 4: Alignment
    │       └── Column          // Level 5: Layout
    │           ├── Text
    │           └── Text
    └── FloatingActionButton

ဒီလိုမျိုး လုပ်ထားခြင်းအားဖြင့် flutter app ရဲ့ အစိတ်အပိုင်းတခုခုမှာ အပြောင်းအလဲ​ ရှိပြီဆို အဲ့ဒီအစိတ်အပိုင်းကိုပဲ re-render လုပ်သွားလို့ရပါတယ်။ ဒါကိုတော့ နောက်နေ့တွေမှာ ရှင်းပြသွားပါမယ်။

Design Systems

အခု ဒီမှာ ကြည့်မယ်ဆို ထိပ်ဆုံးမှာ MaterialApp ဆိုတာကို တွေ့ရမှာပဲ ဖြစ်ပါတယ်။ ဒါကိုတော့ material design system ကို အသုံးပြုချင်တဲ့အခါ သုံးပါတယ်။ တကယ်လို့ iOS design system သုံးချင်တယ်ဆိုရင်တော့ CupertinoApp ဆိုတာကိုပြောင်းသုံးလိုက်လို့ရပါတယ်။

Material component widgets
A catalog of Flutter’s material component widgets. Visual, behavioral, and motion-rich widgets implementing the Material 3 design specification.
Cupertino widgets
A catalog of Flutter’s cupertino widgets. Beautiful and high-fidelity widgets that align with Apple’s Human Interface Guidelines for iOS and macOS.

Material ကတော့ Google ရဲ့ design system ဖြစ်ပြီးတော့ Cupertino ဆိုတာကတော့ Apple ရဲ့ design system ဖြစ်ပါတယ်။ Cupertino ကတော့ Apple ရဲ့နောက်ဆုံး liquid glass မဟုတ်သေးဘဲ အရင် design system ပဲ ဖြစ်ပါတယ်။

Stateless Widgets

Flutter app ရဲ့တည်ဆောက်ပုံတွေ design system တွေအကြောင်းပြောပြီးပြီဆိုတော့ အခု Stateless widget တွေဆိုတာ ဘာတွေလဲ စပြီးတော့ ကြည့်လိုက်ကြရအောင်ပါ။ stateless widget ဆိုတာကတော့ widget အနေနဲ့ တည်ဆောက်ပြီးတဲ့အခါ မပြောင်းလဲတော့တဲ့ widget တွေကိုပြောတာပဲ ဖြစ်ပါတယ်။ ဆိုလိုတာကတော့ သူ့ထဲမှာ ပြနေတဲ့ text value တွေ, image value တွေက မပြောင်းလဲတော့တဲ့အခါမျိုးမှာ သုံးကြပါတယ်။ immutable ဖြစ်တယ်လို့လဲ ပြောလို့ရပါတယ်။

ဥပမာ စာရွက်ပေါ်မှာ print လုပ်လိုက်သလိုပေါ့။ ပေးထားတဲ့ data တွေနဲ့ print လုပ်ပြီးတဲ့အခါ ပြင်ဆင်လို့မရတော့ပါဘူး။ တကယ်လို့ data အသစ်နဲ့ထပ်လိုချင်ရင် ထပ်ပြီး print ပေးရမှာပါ။

Stateless widget တွေမှာ state ဆိုတာမျိုးလဲ မရှိတဲ့အတွက် သူတို့ကို data တွေပေးဖို့လိုတဲ့အခါ အပြင်ကနေ ထည့်ပေးရပါတယ်။ ထည့်ပေးတဲ့ data ကို သူတို့က သုံးပြီးတော့ widget တွေကို တည်ဆောက်ပါတယ်။ တည်ဆောက်ပြီးတဲ့ widget ကို ပြောင်းလဲတာတွေ လုပ်လို့မရတော့ပါဘူး။ data အသစ်ပြချင်တဲ့အခါ ရှိပြီးသား widget ကို ဖျက်ပြီးတော့ အသစ်ဆောက်ရမှာပဲ ဖြစ်ပါတယ်။

Why use Stateless Widgets?

ဒီတော့ stateless widget ကိုဘာကြောင့် သုံးကြသလဲ၊ ဘာအကျိုးကျေးဇူးတွေရှိလဲ ကြည့်ကြည့်ရအောင်ပါ။

  • Performance - Stateless widget တွေက ပြောင်းလဲမှုမရှိတဲ့အတွက် state နဲ့ပတ်သက်တာတွေ မပါတော့ပါဘူး။ ဒီတော့ render လုပ်ရတာမြန်ပါတယ်။
  • Memory Efficiency - Stateless widget တွေက state info တွေ ကိုင်တွယ်စရာမလိုတဲ့အတွက် memory ပေါ်မှာ state object တွေ၊ controller တွေ၊ subscriptions တွေ ဘာမှ သိမ်းထားဖို့မလိုတော့ပါဘူး။ ဒီတော့ memory usage သက်သာပါတယ်။
  • Predictability - Stateless တွေက data တူတာဝင်ရင်ပြတာတူမှာ ဖြစ်တဲ့အတွက် ဘာထွက်လာမလဲ၊ ဘယ်လိုပြမလဲဆိုတာ စဥ်းစားရလွယ်ပါတယ်။

Example

ဒါဆို stateless widget တခုကို ဘယ်လိုတည်ဆောက်လဲ ကြည့်ကြည့်ရအောင်ပါ။

import 'package:flutter/material.dart';

class ProfileCard extends StatelessWidget {
  // 1. PROPERTIES - Data passed from parent
  final String name;
  final String role;

  // 2. CONSTRUCTOR - Always const when possible
  const ProfileCard({
    super.key, // Enables Flutter's optimization
    required this.name, // Must be provided
    required this.role, // Must be provided
  });

  // 3. BUILD METHOD - The blueprint
  @override
  Widget build(BuildContext context) {
    // This returns the UI tree
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        children: [
          const Text('Profile Information'),
          Text(name, style: Theme.of(context).textTheme.displaySmall),
          Text(role, style: Theme.of(context).textTheme.titleSmall),
        ],
      ),
    );
  }
}

Stateless widget တခုဆောက်မယ်ဆို StatelessWidget class ကို extends လုပ်ပြီး create လုပ်ပါတယ်။ ဒါရှေ့ရက်တွေမှာ ဆွေးနွေးခဲ့တဲ့ Object Oriented Programming (OOP) ကို အခြေခံထားတာ ဖြစ်ပါတယ်။ name, role ဆိုတဲ့ properties တွေကိုလဲ တွေ့ရမှာပါ။ သူတို့ကိုတော့ ဒီ widget ကိုခေါ်တဲ့ နေရာက ထည့်ပေးရမှာပဲ ဖြစ်ပါတယ်။ သူတို့ကိုတော့ widget tree ထဲမှာ ပြသွားနိုင်ပါတယ်။

build ဆိုတာကတော့ UI ကို render လုပ်မယ့် method ပဲ ဖြစ်ပါတယ်။ Stateless widget ဖြစ်တဲ့အတွက် ဝင်လာတဲ့ name, role တွေနဲ့ build method ကို ခေါ်ပြီးတော့ UI component တွေ တည်ဆောက်ပါတယ်။

build method မှာ context ဆိုတဲ့ BuildContext parameter ကို တွေ့ရမှာပါ။ BuildContext ကိုသုံးပြီးတော့ widget tree ကို reference လုပ်ပြီး လိုတဲ့ info တွေ ရယူနိုင်ပါတယ်။ အခုဒီမှာ Theme.of(context).textTheme.... ဆိုပြီး သုံးတာကို တွေ့ရမှာပါ။ ဒါကတော့ context ကို သုံးပြီးတော့ Text Theme ကို reference လှမ်းလုပ်တာပဲ ဖြစ်ပါတယ်။ ဒါ့အပြင် screen size တွေ widget ရဲ့ size တွေကိုလဲ ရယူနိုင်မှာပဲ ဖြစ်ပါတယ်။

@override
Widget build(BuildContext context) {
  // Access theme colors from parent
  final theme = Theme.of(context);
  final primaryColor = theme.colorScheme.primary;
  
  // Get screen size
  final screenWidth = MediaQuery.of(context).size.width;
  
  // Navigate to another screen
  Navigator.of(context).push(...);
  
  // Show a dialog
  showDialog(context: context, ...);
  
  return Container(
    color: primaryColor,
    width: screenWidth * 0.8,
    child: Text('Hello'),
  );
}

build method ကနေ return ပြန်တာက Widget ဖြစ်နေဖို့လိုပါတယ်။ ဒီမှာဆိုရင် Container widget ကို return ပြန်ထားတာ တွေ့နိုင်ပါတယ်။

ဒီ ProfileCard ကို အသုံးပြုမယ်ဆို အခုလိုမျိုး အသုံးပြုလို့ရပါတယ်။

const ProfileCard(
  name: "Arkar Min Tun", 
  role: "Admin"
),

ဒီမှာ const ကို သုံးထားတာကို တွေ့ရမှာပါ။ ဒါကတော့ ပြောင်းလဲဖို့မရှိတဲ့ widget တွေဆို const ကို သုံးခြင်းအားဖြင့် performance ကို မြှင့်တင်ပေးနိုင်မှာပဲ ဖြစ်ပါတယ်။ Flutter rendering engine ကို ဒါက ပြောင်းလဲမှာမဟုတ်ဘူးလို့ ပြောလိုက်တာနဲ့ တူတူပဲ ဖြစ်ပါတယ်။ ဒီတော့ မလိုအပ်ဘဲ rendering တွေ မလုပ်တော့တဲ့အတွက် performance ပိုကောင်းလာမှာပဲ ဖြစ်ပါတယ်။

// Without const - created at runtime (slow)
Text('Hello')

// With const - created at compile-time (instant)
const Text('Hello')

တကယ်လို့ ဒီ widget ကိုပဲ value တူတူနဲ့ ထပ်ခါထပ်ခါ create တဲ့အခါ component တွေက memory instance တခုကိုပဲ သုံးပြီးတော့ create လုပ်ပါတယ်။ Rebuild လုပ်တဲ့အခါမှာလဲ const နဲ့ ကြေငြာမထားတာတွေကို re-render လုပ်သွားမှာ ဖြစ်ပါတယ်။ ဒီတော့ const keyword ကို သုံးလို့ရတဲ့ နေရာတွေမှာ သုံးပေးခြင်းအားဖြင့် performance ကို မြှင့်တင်နိုင်ပါပဲ ဖြစ်ပါတယ်။

ဒါဆိုရင်တော့ Stateless widget တွေနဲ့ပတ်သက်ပြီး အတော်အသင့် နားလည်လောက်ပြီ ထင်ပါတယ်။ မနက်ဖြန်မှာတော့ Stateful widget တွေအကြောင်း ဆွေးနွေးသွားမှာ ဖြစ်ပါတယ်။ အမြည်းအနေနဲ့ stateless နဲ့ stateful ကွာခြားတာလေးကို အောက်မှာ ပြပေးထားပါတယ်။

StatelessWidget vs StatefulWidget Preview

Feature StatelessWidget StatefulWidget
Data Changes No (immutable) Yes (mutable)
Performance ⚡⚡⚡⚡⚡ Faster ⚡⚡⚡⚡ Slightly slower
Lifecycle Only build() initState(), build(), dispose()
Use Cases Icons, labels, static cards Forms, animations, interactive elements
Memory Lightweight Small overhead for state management

ဒီနေ့ Day 16 အတွက်ကတော့ ဒီလောက်ပဲ ဖြစ်ပါတယ်။ အဆုံးထိ ဖတ်ပေးတဲ့အတွက် အများကြီး ကျေးဇူးတင်ပါတယ်။ နားမလည်တာတွေ အဆင်မပြေတာတွေ ရှိခဲ့ရင်လဲ အောက်မှာပေးထားတဲ့ discord server ထဲမှာ လာရောက်ဆွေးနွေးနိုင်ပါတယ်။ နောက်နေ့တွေမှာလဲ ဆက်လက်ပြီး sharing လုပ်သွားပေးသွားမှာ ဖြစ်တဲ့အတွက် subscribe လုပ်ထားဖို့ ဖိတ်ခေါ်ပါတယ်။