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

2,841

A typical builder function would look like this:

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

However, if builder is very expensive, it may be possible to move some of it out of the builder, and into a child parameter:

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

can become:

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
)

This effectively caches VeryExpensiveWidget, building it once and then using that for all future calls to the builder.

The problem is that you may not pass a child in. In the first example, we don't need the child parameter, and this is totally fine. However, it means that child is now null. Because this is allowed behaviour, child must be a Widget?

In your case, you always pass in a child parameter, so you can guarantee that the child passed into builder is non-null, so it is safe to use child! to forcibly convert child into a Widget

Your builder would then become:

builder: (_, cart, child) => Badge(child: child!, value: cart.itemCount.toString()),
Share:
2,841
Dadoh
Author by

Dadoh

Updated on November 28, 2022

Comments

  • Dadoh
    Dadoh over 1 year

    I'm trying to build a Consumer but I'm getting this

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

    error underlined on the child inside the builder. Here's the code:

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

    Here's the Badge item it refers to:

      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,
              ),
            ),
          ),
        )
      ],
    );