context_di 0.2.0-Preview copy "context_di: ^0.2.0-Preview" to clipboard
context_di: ^0.2.0-Preview copied to clipboard

Flutter Provider based Dependency Injection Tool supports two main scopes factory and singleton with code generation

pub package

Project is based on Provider package. Main goal is to create a tool that will help reduce boilerplate code and make it easier to work with dependency injection via Provider.

Features #

2 scopes are supported:

  • factory scope (creates instance every time)
  • singleton scope (one instance per feature)

Parameterized factories

final bloc = context.resolveWithParams<Bloc>((id: _id));

Scopes based on widget tree lifecycle: [dispose.gif]

Added Code Generation #

add build_runner and [context_di_generator] to your project

dev_dependencies:
  build_runner:
  context_di_generator:

create empty feature class that extends FeatureDependencies with _$

part 'basic.feature.dart';

typedef EntityBlocParams = ({int id});

void _dispose(BuildContext context, Repository instance) => instance.dispose();

@Feature()
@Singleton(Repository, as: RepositoryInterface, dispose: _dispose)
@Factory(ListBloc)
@Factory(EntityBloc, params: EntityBlocParams)
class Basic extends FeatureDependencies with _$BasicFeatureMixin {
  const Basic({super.key, super.builder});
}

then run dart run build_runner build -d to generate feature file

Getting started #

Create a feature class that extends FeatureDependencies and override register method. When you need to register a dependency, use registerSingleton, registerSingletonAs, registerFactory or registerParamsFactory methods.

typedef EntityBlocParams = ({int id});

class BasicFeature extends FeatureDependencies {
  const BasicFeature({super.key, super.builder});

  @override
  List<Registration> register(BuildContext context) {
    return [
      registerSingletonAs<Repository, RepositoryInterface>(
        (context) => Repository(context.resolve()),
        dispose: (context, instance) => instance.dispose(),
      ),
      registerFactory(
        (context) => ListBloc(context.resolve<RepositoryInterface>()),
      ),
      registerParamsFactory(
        (context, EntityBlocParams params) => EntityBloc(
          params.id,
          context.resolve(),
        ),
      ),
    ];
  }
}

Add to your widget tree

@RoutePage()
class BasicFeaturePage extends StatelessWidget {
  const BasicFeaturePage({super.key});

  @override
  Widget build(BuildContext context) {
    return BasicFeature(builder: (context) {
      return _Content();
    });
  }
}

And resolve dependencies in feature co

class _Content extends StatefulWidget {
  const _Content();

  @override
  State<_Content> createState() => _ContentState();
}

class _ContentState extends State<_Content> {
  late final ListBloc _listBloc;

  int? _selectedId;

  @override
  void initState() {
    _listBloc = context.resolve<ListBloc>();
    super.initState();
  }

  @override
  void dispose() {
    _listBloc.close();
    super.dispose();
  }

  //...
}
@RoutePage()
class EntityPage extends StatelessWidget {
  final int _id;

  const EntityPage({super.key, required int id}) : _id = id;

  @override
  Widget build(BuildContext context) {
    return BlocProvider<EntityBloc>(
      create: (_) => context.resolveWithParams((id: _id)),
      child: BlocBuilder<EntityBloc, EntityState>(builder: (context, state) {
        return Scaffold(
          body: switch (state) {
            Initial() => Center(child: CircularProgressIndicator.adaptive()),
            Loaded() => _Content(state),
          },
        );
      }),
    );
  }
}

basic resolve

 final listBloc = context.resolve<ListBloc>();

parametrized resolve

 var create = (_) => context.resolveWithParams((id: _id));

Additional information #

IMPORTANT NOTICE! You can use resolve or resolveWithParams only in feature context, in lover levels of widget tree. If you have some core dependencies register them on app level:

class MyApp extends StatelessWidget {
  MyApp({super.key});

  final _router = AppRouter();

  @override
  Widget build(BuildContext context) {
    return _RootDependencies(
      builder: (context) => MaterialApp.router(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        routerConfig: _router.config(),
      ),
    );
  }
}

class _RootDependencies extends FeatureDependencies {
  const _RootDependencies({super.builder});

  @override
  List<Registration> register(BuildContext context) {
    return [
      registerSingleton<Logger>((_) => Logger()),
    ];
  }
}
4
likes
0
points
29
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter Provider based Dependency Injection Tool supports two main scopes factory and singleton with code generation

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, provider

More

Packages that depend on context_di