收到 "The argument type 'Widget?' can't be assigned to the parameter type 'Widget'" 错误

Getting "The argument type 'Widget?' can't be assigned to the parameter type 'Widget'" error

我正在尝试构建一个 Consumer,但我得到了这个

The argument type 'Widget?' can't be assigned to the parameter type 'Widget'.

错误在 builder 中的 child 上加下划线。 这是代码:

Consumer<Cart>(
        builder: (_, cart, ch) => Badge(
              child: ch,
              value: cart.itemCount.toString(),
            ),
        child: IconButton(
          icon: Icon(
            Icons.shopping_cart,
          ),
          onPressed: () {},
        ),
      ),

这是它引用的徽章项目:

  Widget build(BuildContext context) {
return Stack(
  alignment: Alignment.center,
  children: [
    child,
    Positioned(
      right: 8,
      top: 8,
      child: Container(
        padding: EdgeInsets.all(2.0),
        // color: Theme.of(context).accentColor,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10.0),
          color: Theme.of(context).accentColor,
        ),
        constraints: BoxConstraints(
          minWidth: 16,
          minHeight: 16,
        ),
        child: Text(
          value,
          textAlign: TextAlign.center,
          style: TextStyle(
            fontSize: 10,
          ),
        ),
      ),
    )
  ],
);

典型的构建器函数如下所示:

Consumer<FooModel>(
  builder: (context, model, child) {
    return Text(model.foo());
  }
)

但是,如果 builder 非常昂贵,则可以将其中一些移出构建器,并放入 child 参数中:

Consumer<FooModel>(
  builder: (context, model, child) {
    return Column(children: [
      Text(model.foo()),
      VeryExpensiveWidget(),  // this gets rebuilt every time FooModel updates
    ])
  }
)

可以变成:

Consumer<FooModel>(
  builder: (context, model, child) {
    return Column(children: [
      Text(model.foo()),
      child,  // this gets passed into the builder function
    ])
  },
  child: VeryExpensiveWidget(),  // pass it as a child of the consumer
)

这有效地缓存 VeryExpensiveWidget,构建它一次,然后将其用于所有未来对构建器的调用。

问题是你可能没有传入child。在第一个例子中,我们不需要child参数,这完全没问题。但是,这意味着 child 现在是 null。因为这是允许的行为,所以 child 必须是 Widget?

在你的情况下,你总是传入一个child参数,所以你可以保证传递给builderchild是非空的,所以可以安全使用child! 强制将 child 转换为 Widget

您的构建器将变为:

builder: (_, cart, child) => Badge(child: child!, value: cart.itemCount.toString()),

最后,创建的 Provider 的 Consumer-Type 'Listener' 代码如下所示:

Consumer<CartDataProvider>(
            builder: (_, receivedCartDataProvider, fixedChildThatWeProvide) {
              return Badge(
                child: fixedChildThatWeProvide!,
                value: receivedCartDataProvider.cartItemCount.toString(),
                color: Colors.white,
              );
            },
            child: IconButton(
              icon: Icon(Icons.shopping_cart),
              onPressed: () {},
            ),
          )