Skip to content
This repository was archived by the owner on Jan 19, 2023. It is now read-only.

devobs/value_cubit

Repository files navigation

A dart package that helps to implement basic states for BLoC library to perform, load and fetch data.

/!\ This repository is now deprecated and has been transfered in https://github.com/devobs/value_state.

pub package Test codecov License: MIT

Features

  • Provides all necessary states for data : init, waiting, value/no value and error states,
  • A ValueCubit class to simplify Cubit subclassing,
  • A RefreshValueCubit class like ValueCubit with refreshing capabilities,
  • Some helpers perform (an extension on Cubit) to emit intermediate states while an action is intended to update state : the same state is reemitted with attribute refreshing at true.

Usage

Basic example

class CounterCubit extends ValueCubit<int> {
  var _value = 0;

  // Put your WS call that can be refreshed
  Future<int> _getCounterValueFromWebService() async => _value++;

  Future<void> increment() => perform(() async {
        // [perform] generate intermediate or final states such as PendingState,
        // concrete subclass of ReadyState with right [ReadyState.refreshing] value
        // or ErrorState if an error is raised.
        final result = await _getCounterValueFromWebService();

        emit(ValueState(result));
      });

  void clear() {
    _value = 0;
    emit(const PendingState());
  }
}

main() async {
  final counterCubit = CounterCubit();

  counterCubit.increment(); // to emit first value

  await for (final state in counterCubit.stream) {
    if (state is WaitingState<int>) {
      print('Waiting for value');
    } else if (state is ReadyState<int>) {
      // smart cast [state] in [ReadyState] to access [ReadyState.hasError] attribute
      if (state.hasError) {
        print('Error');
      } else if (state is WithValueState<int>) {
        // deeper smart cast of [state] in [WithValueState] to access [WithValueState.value]
        // attribute.
        print('Value : ${state.value}');
      }
    }
  }

  // increment values 2 times
  counterCubit.increment();
  counterCubit.increment();
}

If your cubit is only a getter with the need to refresh your cubit state, you can simplify the implementation ValueCubit with RefreshValueCubit.

class CounterCubit extends RefreshValueCubit<int> {
  var _value = 0;

  // Put your WS call that can be refreshed
  Future<int> _getCounterValueFromWebService() async => _value++;

  @override
  Future<void> emitValues() async {
    final result = await _getCounterValueFromWebService();

    emit(ValueState(result));
  }
}

Update your value (increment in our example) by calling myCubit.refresh().

With Flutter and Flutter BLoC library

This example shows how different value states from this library help developpers to show load step data widgets.

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

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return BlocBuilder<CounterCubit, BaseState<int>>(builder: (context, state) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo Home Page'),
        ),
        body: DefaultTextStyle(
          style: const TextStyle(fontSize: 24),
          textAlign: TextAlign.center,
          child: state is ReadyState<int>
              ? Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    if (state.refreshing) const LinearProgressIndicator(),
                    const Spacer(),
                    if (state.hasError)
                      Text('Expected error.',
                          style: TextStyle(color: theme.errorColor)),
                    if (state is WithValueState<int>) ...[
                      if (state.hasError)
                        const Text('Previous counter value :')
                      else
                        const Text('Actual counter value :'),
                      Text(
                        state.value.toString(),
                        style: theme.textTheme.headline4,
                      ),
                    ],
                    if (state is NoValueState<int>) const Text('No Value'),
                    const Spacer(),
                  ],
                )
              : const Center(child: CircularProgressIndicator()),
        ),
        floatingActionButton: state is! ReadyState<int>
            ? null
            : FloatingActionButton(
                onPressed: state.refreshing
                    ? null
                    : context.read<CounterCubit>().increment,
                tooltip: 'Increment',
                child: state.refreshing
                    ? SizedBox.square(
                        dimension: 20,
                        child: CircularProgressIndicator(
                            color: theme.colorScheme.onPrimary))
                    : const Icon(Icons.refresh)),
      );
    });
  }
}

The whole code of this example is available in example/flutter.

Models

State diagram

State diagram

Class diagram

Class diagram

Feedback

Please file any issues, bugs or feature requests as an issue on the Github page.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published