搜索插件、代码仓与 APP 分类

插件详情v4.2.2

get_it_mixin

适用于无状态和有状态控件的混入,使将控件绑定到 GetIt 中存储的对象更加容易。

AndroidiOSWebmacOSWindowsLinux
近 30 天下载
2930
喜欢数
141
Pub 分数
130

安装插件

flutter pub add get_it_mixin

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

get_it_mixin 包为 Stateless 和 Stateful Widget 提供了一个便捷的 mixin,可轻松绑定到 GetIt 中注册的依赖项,GetIt 是一个流行的依赖注入库。通过混入 GetItMixin,widget 可以在 build 方法中直接访问注入的服务、仓库或其他对象,而无需手动获取它们。这减少了样板代码并提高了可读性,尤其是在依赖管理至关重要的大型 Flutter 应用中。该 mixin 与 GetIt 的 API 无缝集成,并支持所有主要平台。

适合场景

  • 简化小部件中的依赖项访问
  • 使用 GetIt 时减少样板代码
  • 在UI层实现关注点的清晰分离
  • 通过注入服务简化状态管理
  • 通过将小部件逻辑与具体实现解耦来提高可测试性

主要特点

  • 与 GetIt 的轻松集成
  • 减少重复的依赖项查找
  • 支持无状态和有状态组件
  • 最小代码开销
  • 适用于所有 Flutter 平台

适合对象

  • 使用 GetIt 进行依赖注入的开发者
  • 旨在减少小部件样板代码的项目
  • 优先考虑可维护的 UI 代码的团队
  • 具有复杂依赖关系树的 Flutter 应用
  • 需要在用户界面和业务逻辑之间进行清晰分离的应用程序

使用建议

  • 需要先设置 GetIt
  • 如果过度使用,可能会增加复杂性
  • 对于依赖项较少的简单应用程序,不需要
  • 最好与正确的依赖项注册配合使用
  • 仅限基于 GetIt 的 DI 工作流

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

Hi my friends,

I recently published my new package watch_it https://github.com/escamoteur/watch_it, an overhauled version of the get_it_mixin but with a more intuitive and streamlined API. Porting an existing project using get_it_mixin is really easy and quick.

To better connect with my package users I know opened a Discord Server to support my packages https://discord.gg/ZHYHYCM38h

This package here won't be further maintained. You can continue using the latest version but I won't add new features or fix bugs.

get_it_mixin

A set of mixins that allow widgets to watch data registered with GetIt. Widgets that watch data will rebuild automatically whenever that data changes.

Supported data types that can be watched are ChangeNotifier, ValueNotifier, Stream and Future.

ChangeNotifier based example:

// Create a ChangeNotifier based model
class UserModel extends ChangeNotifier {
  get name = _name;
  String _name = '';
  set name(String value){
    _name = value;
    notifyListeners();
  }
  ...
}

// Register it 
getIt.registerSingleton<UserModel>(UserModel());

// Watch it
class UserNameText extends StatelessWidget with GetItMixin {
  @override
  Widget build(BuildContext context) {
    final userName = watchOnly((UserModel m) => m.name);
    return Text(userName);
  }
}

Reading Data

Reading data is already quite easy with GetIt, but it gets even easier with the mixin. Just add a GetItMixin to a StatelessWidget and call get<T>:

class MyWidget extends StatelessWidget with GetItMixin {
  void _handleSubmitPressed() {
    final email = get<Model>().emailAddress;
    ...
  }
}

You can do the same thing on StatefulWidget using a GetItStatefulWidgetMixin and GetItStateMixin:

class MyWidget extends StatefulWidget with GetItStatefulWidgetMixin {
  _MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> with GetItStateMixin {
  void _handleSubmitPressed() {
    final email = get<Model>().emailAddress;
    ...
  }
}

NOTE: The GetItMixin API is generally the same regardless of whether you use Stateless or Stateful widgets.

Watching Data

Where GetItMixin really shines is data-binding. It comes with a set of watch methods to rebuild a widget when data changes.

Imagine you had a very simple shared model, with multiple fields, one of them being country:

class Model {
    final country = ValueNotifier<String>('Canada');
    ...
}
getIt.registerSingleton<Model>(Model());

You could tell your view to rebuild any time country changes with a simple call to watchX:

class MyWidget extends StatelessWidget with GetItStatefulWidgetMixin {
  @override
  Widget build(BuildContext context) {
    String country = watchX((Model x) => x.country);
    ...
  }
}

There are various watch methods, for common types of data sources, including ChangeNotifier, ValueNotifier, Stream and Future:

API Description
.watch Bind to a ValueListenable value
.watchX Bind to the results of a select method on a ValueListenable value
.watchOnly Bind to a basic Listenable (like ChangeNotifier)
.watchXOnly Bind to the results of a select method on a Listenable
.watchStream Subscribe to a Stream
.watchFuture Bind to a Future

Just call watch_ to listen to the data type you need, and GetItMixin will take care of cancelling bindings and subscriptions when the widget is destroyed.

The primary benefit to the watch methods is that they eliminate the need for ValueListenableBuilders, StreamBuilder etc. Each binding consumes only one line and there is no nesting.

Here we watch three ValueListenable which would normally be three builders, 12+ lines of code and several levels of indentation. With GetItMixin, it's three lines:

class MyWidget extends StatelessWidget with GetItMixin {
  @override
  Widget build(BuildContext context) {
    bool loggedIn = watchXOnly((UserModel x) => x.isLoggedIn);
    String userName = watchXOnly((UserModel x) => x.user.name);
    bool darkMode = watchXOnly((SettingsModel x) => x.darkMode);
    ...
  }
}

This can be used to eliminate StreamBuilder and FutureBuilder from your UI as well:

class MyWidget extends StatelessWidget with GetItMixin {
  @override
  Widget build(BuildContext context) {
    final currentUser = watchStream((UserModel x) => x.userNameUpdates, 'NoUser');
    final ready = watchFuture((AppModel x) => x.initializationReady, false).data;
    bool appIsLoading = ready == false || currentUser.hasData == false;
    
    if(appIsLoading) return CircularProgressIndicator();
    return Text(currentUser.data);    
  }
}
Side Effects / Event Handlers

Instead of rebuilding, you might instead want to show a toast notification or dialog when a Stream emits a value or a ValueListenable changes.

To run an action when data changes you can use the register methods:

API Description
.registerHandler Add an event handler for a ValueListenable
.registerStreamHandler Add an event handler for a Stream
.registerFutureHandler Add an event handler for a Future

The first param in the register methods is a select delegate that can be used to watch a specific field. The second param is the action which will be triggered when that field changes:

class MyWidget extends StatelessWidget with GetItMixin {
  @override
  Widget build(BuildContext context) {
    registerHandler(
        (Model x) => x.name,
        (context, value, cancel) => showNameDialog(context, value));
    ...
  }
}

In the example above you see that the handler function receives the value that is returned from the select delegate ((Model x) => x.name), as well as a cancel function that the handler can call to cancel registration at any time.

As with watch calls, all registerHandler calls are cleaned up when the Widget is destroyed.

Rules

There are some important rules to follow in order to avoid bugs with the watch methods:

  • watch methods must be called within build()
    • It is good practice to define them at the top of your build method
  • must be called on every build, in the same order (no conditional watching). This is similar to flutter_hooks.
  • do not use them inside of a builder as it will break the mixins ability to rebuild

isReady() and allReady()

A common use case is to toggle a loading state when side effects are in-progress. To check whether any registered actions have completed you can use allReady() and isReady<T>(). These methods return the current state of any registered async operations and a rebuild is triggered when they change.

class MyWidget extends StatelessWidget with GetItMixin {
  @override
  Widget build(BuildContext context) {
    allReady(onReady: (context)
      => Navigator.of(context).pushReplacement(MainPageRoute()));
    return CircularProgressIndicator();
  }
}

Check out the GetIt docs for more information on the isReady and allReady functionality: https://pub.dev/packages/get_it

Pushing a new GetIt Scope

With pushScope() you can push a scope when a Widget/State is mounted, and automatically pop when the Widget/State is destroyed. You can pass an optional init or dispose function.

  void pushScope({void Function(GetIt getIt) init, void Function() dispose});

This can be very useful for injecting mock services when views are opened so you can easily test them. Of course you can also push and pop scope directly from your tests as well!

Find out more!

For more background on the history of GetItMixin you can check out the README_EXTENDED.

For a more complete explanation of the API watch the presentation: GetIt in action By Thomas Burkhart.

所属分类

依赖

依赖清单 2 项

  • functional_listener^2.1.0
  • get_it^7.6.0

源码仓库

使用此插件的项目