Pub Version Flutter CI

一个 Flutter 包,用于根据 Listenable 的更新来控制小部件的重建。

什么是 Grab?

Grab 类似于 ValueListenablebuilerAnimatedBuilder,但它并非像它们一样的 Widget。它附带了 BuildContext 的 mixins 和扩展。

如果一个 Grab mixin 被添加到 Widget 中,并且在该 Widget 中使用了 grab()grabAt() 扩展方法并传入了某个 Listenable,那么当 Listenable(或其特定部分)更新时,Widget 就会被重建。

非常适合状态管理

这个包所做的只是根据 Listenable 的变化来重建 Widget。尽管如此简单,但如果与像 get_it 这样的 DI 包结合使用,它就能成为一个强大的状态管理工具。

只要在使用 grab()grabAt() 时,Listenable 可以通过任何方式获得,Grab 就能正常工作,因此您可以使用您喜欢的 DI 包来传递 Listenable。

动机

下面的博文真的启发了该包的作者。它展示了一张关于状态管理可以多简单的图片。

将这个想法、某种 DI 和 Grab 结合起来,您可以专注于创建一个出色的应用程序,而无需理解如何使用它。这是比其他具有更大 API 表面的包的优势。

支持的 Listenables

Listenable 可以是继承自 Listenable 的任何东西;ChangeNotifier、ValueNotifier、TextEditingController、Animation / AnimationController、ScrollController 等。

用法

Mixins

StatelessGrabMixinStatefulGrabMixin 添加到您想使用扩展的 Widget 中。

class MyWidget extends StatelessWidget with StatelessGrabMixin
class MyWidget extends StatefulWidget with StatefulGrabMixin

每个 mixin 都有一个别名。如果您喜欢更短的名称,请将 StatelessGrabMixin 使用 Grab,将 StatefulGrabMixin 使用 Grabful

class MyWidget extends StatelessWidget with Grab
class MyWidget extends StatefulWidget with Grabful

扩展

您可以在 BuildContext 上使用 grab()grabAt()。它们就像 providerwatch()select()

确保将 mixin 添加到使用这些扩展的 StatelessWidget/StatefulWidget 中。否则会出错。

grab()

grab() 监听传递给它的 Listenable,并且每当 Listenable 更新时,属于该 BuildContext 的 Widget 都会被重建。

final notifier = ValueNotifier(0);

@override
Widget build(BuildContext context) {
  final count = context.grab<int>(counterNotifier);
  return Text('$count');
}

返回值是 Listenable 本身,或者如果 Listenable 是 ValueListenable,则是其值。

在上面的示例中,Listenable 是一个继承自 ValueListenableValueNotifier,因此 grab() 返回的 count 不是 Listenable 本身,而是 ValueNotifier 的值。

grabAt()

只有当选择器(作为第二个参数传递的回调函数)返回的值发生变化时,Widget 才会重建。

final notifier = ValueNotifier(
  Item(name: 'Milk', quantity: 3),
);

@override
Widget build(BuildContext context) {
  final name = context.grabAt(notifier, (Item item) => item.name);
  return Text(name);
}

选择器接收 Listenable 本身,或者如果 Listenable 是 ValueListenable,则接收其值。

在此示例中,notifier 的值是具有 namequantityItem。如果 quantity 的值发生了变化但 name 没有更新,Widget 不会重建。

提示

选择器返回的值可以是任何内容,只要可以使用 == 运算符将其与先前的值进行相等性评估即可。

final bool isEnough = context.grabAt(
  notifier,
  (Item item) => item.quantity > 5,
);

假设上一次构建的数量是 3,如果它更改为 2,则 Widget 不会重建,因为 isEnough 仍然是 false。

GitHub

查看 Github