voyager_bloc 0.2.3

  • Readme
  • Changelog
  • Example
  • Installing
  • new61

voyager_bloc #

pub package Codemagic build astatus codecov

Adds ability to specify used BLoCs on the widget level.

Usage #

Specify wanted blocs per screen in YAML file, like so:

'/my/fancy/path':
  widget: FancyWidget
  bloc:
    - BlocA : 12 # provide config for bloc after :
    - BlocB :
        - field1: "hello"
        - field2: "world"
    - BlocC@foo : "enemy" # use @ to provide named blocs
    - BlocC@bar : "friend"

Use BlocPluginBuilder to provide mappings for your blocs:

BlocPluginBuilder()
  .addBaseBloc<BlocA>((routeContext, config, repository) => /* return BlocA here */)
  .build()

where repository gives you access to other blocs from your the scope of your page.

Class Hierarchy & Bloc Plugin Builder

Flutter Dart has no reflection and runtimeType doesn't contain information about parent classes, therefore voyager bloc plugin builder has specific API to address this issue:

If your bloc class (e.g. ParentBloc) is extending directly from Bloc use:

addBaseBloc<ParentBloc>((routeContext, config, repository) {
    return ParentBloc();
})

If your bloc doesn't extend directly from Bloc but e.g. from ParentBloc you will want to use:

addBloc<ChildBloc, ParentBloc>((routeContext, config, repository) {
    return ChildBloc();
})

Schema Validator #

If you're using schema validation with voyager:codegen you can add the following to cover basics

bloc:
  output: BlocRepository
  import: 'package:voyager_bloc/voyager_bloc.dart'
  input:
    type: array

Accessing Blocs #

Once you are working in the buildContext of Widget you can obtain BlocRepository

final repo = Provider.of<Voyager>(context)["bloc"];

or if you use generated strong types:

final repo = VoyagerProvider.of(context).bloc;

From there you can find blocs by type, e.g.:

final blocA = repo.find<BlocA>();

...and if your bloc was given a specific name, then supply name parameter:

final fooBlocC = repo.find<BlocC>(name: "foo");

0.2.3 #

  • Make BlocPluginBuilder additive

0.2.2 #

  • Update voyager version range

0.2.1 #

  • Update to voyager 1.0.6
  • Coverage tracking (codecov + codemagic + badges)
  • Example cleanup

0.2.0 #

  • Blocks within the repo are now lazy initalized
  • BlocBuilder becomes VoyagerBlocBuilder to avoid naming clash with the BlocLibrary
  • Added example app based on Counter
  • Updated to latest versions of bloc

0.1.0 #

  • Initial voyager_bloc release.

example/lib/main.dart

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:voyager/voyager.dart';
import 'package:voyager_bloc/voyager_bloc.dart';

import './gen/voyager_gen.dart';

class SimpleBlocDelegate extends BlocDelegate {
  @override
  void onEvent(Bloc bloc, Object event) {
    super.onEvent(bloc, event);
    print(event);
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print(transition);
  }

  @override
  void onError(Bloc bloc, Object error, StackTrace stacktrace) {
    super.onError(bloc, error, stacktrace);
    print(error);
  }
}

final paths = loadPathsFromString('''
'/counter' :
  type: counter
  title: Counter
  widget: CounterPage
  bloc:
    - CounterBloc: 42
    - ThemeBloc: dark
''');

final plugins = [
  WidgetPluginBuilder().add<CounterPage>((context) => CounterPage()).build(),
  BlocPluginBuilder()
      .addBaseBloc<CounterBloc>(
          (context, config, repo) => CounterBloc.fromConfig(config))
      .addBaseBloc<ThemeBloc>(
          (context, config, repo) => ThemeBloc.fromConfig(config))
      .build()
];

void main() async {
  BlocSupervisor.delegate = SimpleBlocDelegate();
  runApp(Provider.value(
    value: await loadRouter(paths, plugins, voyagerFactory: voyagerDataFactory),
    child: App(),
  ));
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: VoyagerWidget(path: pathCounter),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final voyager = VoyagerProvider.of(context);
    final counterBloc = voyager.bloc.find<CounterBloc>();
    final themeBloc = voyager.bloc.find<ThemeBloc>();

    return BlocBuilder<ThemeBloc, ThemeData>(
      bloc: themeBloc,
      builder: (context, data) => Theme(
        data: data,
        child: Scaffold(
          appBar: AppBar(title: Text(voyager.title)),
          body: BlocBuilder<CounterBloc, int>(
            bloc: counterBloc,
            builder: (context, count) {
              return Center(
                child: Text(
                  '$count',
                  style: TextStyle(fontSize: 24.0),
                ),
              );
            },
          ),
          floatingActionButton: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Padding(
                padding: EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  child: Icon(Icons.add),
                  onPressed: () {
                    counterBloc.dispatch(CounterEvent.increment);
                  },
                ),
              ),
              Padding(
                padding: EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  child: Icon(Icons.remove),
                  onPressed: () {
                    counterBloc.dispatch(CounterEvent.decrement);
                  },
                ),
              ),
              Padding(
                padding: EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  child: Icon(Icons.update),
                  onPressed: () {
                    themeBloc.dispatch(ThemeEvent.toggle);
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

enum CounterEvent { increment, decrement }

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc(this._initalState) : super();

  factory CounterBloc.fromConfig(dynamic config) {
    return CounterBloc(int.parse(config.toString()));
  }

  final int _initalState;

  @override
  int get initialState => _initalState;

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.decrement:
        yield currentState - 1;
        break;
      case CounterEvent.increment:
        yield currentState + 1;
        break;
    }
  }
}

enum ThemeEvent { toggle }

class ThemeBloc extends Bloc<ThemeEvent, ThemeData> {
  ThemeBloc(this._intialState) : super();

  factory ThemeBloc.fromConfig(dynamic config) {
    ThemeData data;
    switch (config.toString()) {
      case "light":
        data = ThemeData.light();
        break;
      default:
        data = ThemeData.dark();
    }

    return ThemeBloc(data);
  }

  final ThemeData _intialState;

  @override
  ThemeData get initialState => _intialState;

  @override
  Stream<ThemeData> mapEventToState(ThemeEvent event) async* {
    switch (event) {
      case ThemeEvent.toggle:
        yield currentState == ThemeData.dark()
            ? ThemeData.light()
            : ThemeData.dark();
        break;
    }
  }
}

Use this package as a library

1. Depend on it

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


dependencies:
  voyager_bloc: ^0.2.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:voyager_bloc/voyager_bloc.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
30
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
80
Overall:
Weighted score of the above. [more]
61
Learn more about scoring.

We analyzed this package on Oct 17, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.5.1
  • pana: 0.12.21
  • Flutter: 1.9.1+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Maintenance issues and suggestions

Support latest dependencies. (-20 points)

The version constraint in pubspec.yaml does not support the latest published versions for 2 dependencies (bloc, flutter_bloc).

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
bloc ^0.15.0 0.15.0 0.16.1
flutter 0.0.0
flutter_bloc ^0.21.0 0.21.0 0.22.1
voyager >=1.0.0 <2.0.0 1.1.3
Transitive dependencies
charcode 1.1.2
collection 1.14.11 1.14.12
meta 1.1.7
path 1.6.4
provider 3.1.0+1
rxdart 0.22.3
sky_engine 0.0.99
source_span 1.5.5
sprintf 4.0.2
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
vector_math 2.0.8
yaml 2.2.0
Dev dependencies
flutter_test