Sunday, July 24, 2022

Getting Started with Flutter Bloc Pattern

 Bloc Pattern


1. Why Bloc

- Keep your code clarm organized, clean, and maintainable

- Compatible with flutter declarative programming


2. What's Bloc

- A design pattern created by Google to separate Logic from UI 

- There is many library to implement this design pattern. But IMO, you should use the flutter_bloc of Felix Angelo. It is a state management to easier your life

- For every action inside the application, there will be a relative state from it. For example, when the data is fetching, the app should be in a loading state displaying a loading animation on the screen


3. The Core Concepts

- Stream is the foundation of Bloc


3.1 Stream

- Stream is a sequence of async event. Each event is a data event or error event.

- When a stream has dispatched its event, it will also notify to all listener subscribed to it


3.2 Receive Stream

- async* means asynchronous generation function, it generates async data

- yield pushes the data (integer) through the Stream

- await keyword helps to wait for a process to finish before proceeding to the next step


```

Stream<int> dataStream() async* {

for (int i = 0; i<3; i++) {

await Future.delayed(Duration(seconds:3));

yield i;

}

}


Stream<int> stream = dataStream();


stream.listen((event) {

    print("RECEIVE data ${event.toString()}");

  });


```

- async* means asynchronous generation function, it generates async data

- yield pushes the data (integer) through the Stream

- await keyword helps to wait for a process to finish before proceeding to the next step


3.3 Cubit and Bloc


- Cubit is a minimal version of Bloc

- Cubit only emits a stream of states

- Bloc emits a stream of states and receive a stream of event


4. Flutter BLOC

4.1 BlocProvider

- A widget that creates and provides a Bloc to all of its children. A single instance of it can be provided to multi widgets within a tree hierarchy




4.2 Bloc Builder

- BlocBuilder is a widget that helps rebuild the UI based on some Bloc state 

changes

- Rebuild a large UI is a heavy cpu task to compute. That's why you need to wrap the exact part of the UI you want to rebuild inside BlocBuilder. For example, if a text is nested inside a column or a row, dont build entire the column/ row, rather to rebuild the text widge only by wrapping it inside the BlocBuilder

- If you dont provide exactly the cubit/ Bloc in Blocbuilder, it will search for the nearest parent bloc in the tree

5. Code Implementation


counter_app.dart

```

import 'package:flutter/material.dart';


import 'counter/counter.dart';


class CounterApp extends MaterialApp {

  const CounterApp({Key? key}) : super(key: key, home: const CounterPage());

}

```


counter_page.dart

```

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';


import '../counter.dart';

import 'counter_view.dart';


class CounterPage extends StatelessWidget {

  const CounterPage({Key? key}) : super(key: key);


  @override

  Widget build(BuildContext context) {

    return BlocProvider(

      create: (_) => CounterCubit(),

      child: CounterView(),

    );

  }

}

```


counter_cubit.dart

```

import 'package:bloc/bloc.dart';


class CounterCubit extends Cubit<int> {

  CounterCubit() : super(0);


  /// Add 1 to the current state.

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


  /// Subtract 1 from the current state.

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

}

```


counter_view.dart

```

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';


import '../counter.dart';


class CounterView extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    final textTheme = Theme.of(context).textTheme;

    return Scaffold(

      appBar: AppBar(title: const Text('Counter')),

      body: Center(

        child: BlocBuilder<CounterCubit, int>(

          builder: (context, state) {

            return Text('$state', style: textTheme.headline2);

          },

        ),

      ),

      floatingActionButton: Column(

        mainAxisAlignment: MainAxisAlignment.end,

        crossAxisAlignment: CrossAxisAlignment.end,

        children: <Widget>[

          FloatingActionButton(

            key: const Key('counterView_increment_floatingActionButton'),

            child: const Icon(Icons.add),

            onPressed: () => context.read<CounterCubit>().increment(),

          ),

          const SizedBox(height: 8),

          FloatingActionButton(

            key: const Key('counterView_decrement_floatingActionButton'),

            child: const Icon(Icons.remove),

            onPressed: () => context.read<CounterCubit>().decrement(),

          ),

        ],

      ),

    );

  }

}

```

6. Summary

- Bloc is a good pattern to improve the code quality and help easier the state management in app

- Must familiar with stream and reactive programming

- Much of boilerplate code


Reference link:

- https://bloclibrary.dev/#/gettingstarted

No comments:

Post a Comment