Disposing subjects in RxDart - Flutter Blocs

375 Views Asked by At

This may sound naive but I wanted to know if we explicitly need to call the dispose method while working with blocs ? So usually I do something like this :

  1. Create a bloc provider
  2. Define the bloc class and initialise the behaviour/publish subjects
  3. Create a dispose method where we close the streams.

Now, the question is that do we need to explicitly call this dispose method somewhere ? Or does bloc providers automatically do it for us ??

Your help shall be highly appreciated. Thank you.

1

There are 1 best solutions below

0
On

You can use my lib: https://pub.dev/packages/flutter_bloc_pattern, which provides BaseBloc, DisposeCallbackBaseBloc, RxStreamBuilder

Example

  1. File counter_bloc.dart:
import 'dart:async';

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 void Function() dispose,
    required this.increment,
    required this.state,
  }) : super(dispose);

  factory CounterBloc() {
    // ignore: close_sinks
    final incrementController = StreamController<void>();

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

    return CounterBloc._(
      dispose: () async {
        await connection.cancel();
        await incrementController.close();
        print('CounterBloc::disposed');
      },
      increment: () => incrementController.add(null),
      state: state,
    );
  }
}
  1. 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({Key? key}) : super(key: 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.headline6,
        );
      },
    );
  }
}

class IncrementButton extends StatelessWidget {
  const IncrementButton({Key? key}) : super(key: key);

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

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