Counter App with bloc & flutter_bloc

ဒီနေ့တော့ bloc pattern ကို အခြေခံထားတဲ့ flutter_bloc ကို အသုံးပြုပြီး app တခု ဘယ်လို တည်ဆောက်သလဲဆိုတာ ကြည့်ကြည့်ရအောင်ပါ။ Flutter မှာ project လုပ်ပြီဆို ပါတဲ့ counter app ကိုပဲ bloc pattern နဲ့ဆို ဘယ်လိုရေးမလဲ ရှင်းပြပေးသွားမှာ ဖြစ်ပါတယ်။

အရင်ဆုံး flutter project တခုကို Android Studio or VS Code မှာ create လုပ်လိုက်ပါ။ Android Studio ရော VS Code မှာပါ flutter plugin တွေထည့်ပြီး app create လုပ်နိုင်ပါတယ်။ တကယ်လို့ terminal ကနေ လုပ်ချင်ရင်လဲ အခု ပေးထားတဲ့ command နဲ့ လုပ်လို့ရပါတယ်။

flutter create counter_bloc

အခုရေးသွားမယ့် counter app မှာ လိုမယ့် bloc နဲ့ flutter_bloc package တွေကို project ထဲမှာ ဆက်ပြီးတော့ install လုပ်ပါမယ်။

flutter pub add bloc flutter_bloc

ပြီးသွားရင်တော့ lib folder ထဲက main.dart ကို အခုလိုပဲ update လုပ်လိုက်ပါမယ်။

import 'package:counter_bloc/counter/counter.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const CounterApp());
}

class CounterApp extends StatelessWidget {
  const CounterApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Counter',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const CounterPage(),
    );
  }
}

counter_page.dart

ဒါကိုကြည့်မယ်ဆို ကျွန်တော်တို့ CounterPage ကို ဆက်ပြီး တည်ဆောက်ဖို့ လိုတာကို တွေ့ပါလိမ့်မယ်။ CounterPage ကို create မလုပ်ခင် counter အတွက် အသုံးပြုမယ့် cubit (counter_cubit.dart) ကို lib folder ထဲမှာ အခုလိုပဲ တည်ဆောက်ပါမယ်။

import 'package:bloc/bloc.dart';

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);

  void decrement() => emit(state - 1);
}

counter_cubit.dart

ဒီမှာ စပြီးတော့ ကျွန်တော်တို့ bloc library ကို အသုံးချသွားမှာ ဖြစ်ပါတယ်။ Bloc အကြီးစားကို မသုံးဘဲ Cubit ကိုပဲ ဘာလို့ သုံးသလဲဆိုတော့ ကျွန်တော်တို့ အသုံးပြုမယ့် counter app logic က အရမ်းကြီး ရှုပ်ထွေးမနေဘဲ event တွေလောက်ထိ handle လုပ်ဖို့ မလိုအပ်လို့ဘဲ​ ဖြစ်ပါတယ်။

lib folder ထဲမှာ counter_page.dart ကို create လုပ်ပြီး အောက်မှာ ပြထားသလို update လုပ်လိုက်ပါမယ်။

import 'package:counter_bloc/counter_cubit.dart';
import 'package:counter_bloc/counter_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CounterPage extends StatelessWidget {
  const CounterPage({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) => CounterCubit(),
      child: const CounterView(),
    );
  }
}

counter_page.dart

ဒီမှာ ကျွန်တော်တို့ state management အတွက် အသုံးပြုမယ့် CounterCubit ကို BlocProvider နဲ့အတူ create လုပ်ပါမယ်။ ဆိုလိုတာကတော့ အခု create လုပ်တဲ့ CounterCubit ကို လိုအပ်တဲ့နေရာတွေကို provide လုပ်ပေးပါလို့ ပြောလိုက်တာမျိုးပဲ ဖြစ်ပါတယ်။

ဒီမှာ CounterView ဆိုပြီးတော့ child widget တခုထပ်ပြီးတော့ create လုပ်ထားတာကိုလဲ တွေ့ရပါမယ်။ CounterPage widget ထဲမှာပဲ လိုအပ်တဲ့ view component widget တွေကို create လုပ်လို့ရရဲ့သားနဲ့ ဘာလို့မလုပ်ဘဲ CounterView ထပ်ပြီး create လုပ်ရတာလဲဆိုရင်တော့ CounterPage context နဲ့ CounterView context မတူတာကြောင့်ပဲ ဖြစ်ပါတယ်။ CounterView context အပေါ်မှာမှ BlocProvider ကို wrap လုပ်ထားတာကြောင့် CounterView ထဲမှာမှ Cubit ကို အသုံးပြုလို့ရမှာပဲ ဖြစ်ပါတယ်။ counter_view.dart ကို အခုလိုပဲ update လုပ်လိုက်ပါမယ်။

import 'package:counter_bloc/counter_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CounterView extends StatelessWidget {
  const CounterView({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Counter")),
      body: Center(
        child: BlocBuilder<CounterCubit, int>(
          builder: (context, state) {
            return Text(
              "$state",
              style: Theme.of(context).textTheme.headlineLarge,
            );
          },
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () => context.read<CounterCubit>().increment(),
            child: const Icon(Icons.add),
          ),
          const SizedBox(height: 12),
          FloatingActionButton(
            onPressed: () => context.read<CounterCubit>().decrement(),
            child: const Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

counter_view.dart

ဒါဆိုရင်တော့ bloc pattern နဲ့ ရေးထားတဲ့ counter app ကို ရပါပြီ။

0:00
/0:10