Skip to content

hoc081098/flutter_bloc_pattern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

3af59c3 · Jun 18, 2024

History

78 Commits
Jun 18, 2024
Jun 18, 2024
Jun 18, 2024
Jun 18, 2024
Jan 10, 2021
Feb 8, 2019
Sep 23, 2021
Jun 18, 2024
Jan 20, 2021
Jun 18, 2024
Jun 18, 2024
Jun 18, 2024
Jun 18, 2024
May 12, 2021

Repository files navigation

flutter_bloc_pattern

Base class, BLoC provider and rxdart builder for BLoC pattern in Flutter.

Flutter test Pub Pub codecov GitHub Style Hits

Getting Started

1. Add this to your package's pubspec.yaml file

dependencies:
  flutter_bloc_pattern: <latest_version>

2. Implements BaseBloc

import 'package:disposebag/disposebag.dart';
import 'package:flutter_bloc_pattern/flutter_bloc_pattern.dart';
import 'package:rxdart_ext/rxdart_ext.dart';

class MyBloc implements BaseBloc {
  StateStream<String> get stream;

  @override
  void dispose() {}
}

3. Consume BLoC

 final bloc = BlocProvider.of<MyBloc>(context);
 return RxStreamBuilder<String>(
  stream: bloc.stream,
  builder: (context, state) {
    return ...;
  },
);

Example: A port of the standard "Counter Button" example from Flutter

1. File counter_bloc.dart

import 'dart:async';

import 'package:disposebag/disposebag.dart';
import 'package:flutter_bloc_pattern/flutter_bloc_pattern.dart';
import 'package:rxdart_ext/rxdart_ext.dart';

class CounterBloc extends DisposeCallbackBaseBloc {
  /// Inputs
  final VoidAction increment;

  /// Outputs
  final StateStream<int> state;

  CounterBloc._({
    required VoidAction dispose,
    required this.increment,
    required this.state,
  }) : super(dispose);

  factory CounterBloc() {
    final incrementController = StreamController<void>();

    final state$ = incrementController.stream
        .scan<int>((acc, _, __) => acc + 1, 0)
        .publishState(0);

    return CounterBloc._(
      dispose: DisposeBag([incrementController, state$.connect()]).dispose,
      increment: incrementController.addNull,
      state: state$,
    );
  }
}

2. File main.dart

import 'package:example/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc_pattern/flutter_bloc_pattern.dart';

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

  @override
  Widget build(BuildContext context) {
    final bloc = BlocProvider.of<CounterBloc>(context);

    return RxStreamBuilder<int>(
      stream: bloc.state,
      builder: (context, state) {
        return Text(
          'COUNTER 1: $state',
          style: Theme.of(context).textTheme.titleLarge,
        );
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final bloc = context.bloc<CounterBloc>();

    return FloatingActionButton(
      onPressed: bloc.increment,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    );
  }
}