WidjectContainer

Flutter 的依赖注入包

一个简单的 DI 包,用于帮助您的 Flutter 应用程序构建松散耦合的组件。

特点

  • 作用域内的显式构造函数注入。
    • 不使用反射/镜像。
  • 嵌套作用域支持,按 widget 类型隔离依赖项。
  • 作用域依赖项的异步初始化。

安装

  1. 打开您项目的 pubspec.yaml 文件。

  2. 添加一个 git 包依赖项

    dependencies:
      # -------------------------- #
      # Your existing dependencies #
      # -------------------------- #
      widject_container:
        git:
          url: https://github.com/zlatancld/WidjectContainer
    
  3. 执行 flutter pub get

基本用法

创建一个连接到 widget 的作用域并注册所需的类型。类型引用在作用域内请求时自动解析。

class AppScope extends Scope<AppWidget> {
  AppScope(): super(null);

  @override
  void configure(ContainerRegister register) {
    register.add((r) => HelloWorldProvider(), Lifetime.transient).as<MessageProvider>();
    register.addWidget((r, key, _) => AppWidget(r.get(), key: key));
  }
}

类的位置

abstract class MessageProvider {
  String getMessage();
}

class HelloWorldProvider implements MessageProvider {
  @override
  String getMessage()
    => "Hello world!";
}

class AppWidget extends StatelessWidget {
  final MessageProvider _messageProvider;
  
  const AppWidget(this._messageProvider, {super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WidjectContainer Demo',
      home: Scaffold(
        body: Text(_messageProvider.getMessage())
      )
    );
  }
}

main 函数中使用作用域的示例是

void main() {
  var app = AppScope().getWidget();
  runApp(app);
}

Widget Provider

使用 WidgetProvider 来实例化已在作用域中注册的 widget 类型。依赖项会按照作用域注册中定义的进行解析和显式注入。

注册示例

class AppScope extends Scope<AppWidget> {
  ...

  @override
  void configure(ContainerRegister register) {
    ...
    register.addWidget((r, key, _) => NewWidget(r.get(), args, key: key));
  }
}

通过 WidgetProvider 使用示例

class AppWidget extends StatelessWidget {
  final MessageProvider _messageProvider;
  final WidgetProvider _widgetProvider;
  
  const AppWidget(this._messageProvider, this._widgetProvider, {super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WidjectContainer Demo',
      home: Scaffold(
        body: _widgetProvider.getWidget<NewWidget>())
      )
    );
  }
}

嵌套作用域

将 widget 的实例化连接到新的作用域,注册类型并继承来自祖先作用域的引用。当创建需要全新依赖项的新屏幕时,这会很有用。

class ScreenScope extends Scope<ScreenWidget>{
  ScreenScope(super.parentContainer);

  @override
  void configure(ContainerRegister register) {
    register.addWidget((r, key, args) => ScreenWidget(...));
  }
}

父作用域中作用域 widget 绑定的位置是

class AppScope extends Scope<AppWidget> {
  ...

  @override
  void configure(ContainerRegister register) {
    ...
    register.addScopedWidget((r, key, _) => ScreenScope(r));
  }
}

通过 WidgetProvider 使用示例

class AppWidget extends StatelessWidget {
  final MessageProvider _messageProvider;
  final WidgetProvider _widgetProvider;
  
  const AppWidget(this._messageProvider, this._widgetProvider, {super.key});

  @override
  Widget build(BuildContext context) {
    return TextButton(
        onPressed: () => _openChildWidget(context), 
        child: Text(_messageProvider.getMessage())
    );
  }
  
  _openChildWidget(BuildContext context){
    Navigator.push(context, MaterialPageRoute(
      builder: (context) => _widgetProvider.getWidget<ScreenWidget>()));
  }
}

鸣谢

WidjectContainer 的灵感来自

作者

@zlatancld

许可证

MIT

GitHub

查看 Github