You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter将组件抽离至外部类时触发TypeError类型错误

Flutter将组件抽离至外部类时触发TypeError类型错误

看起来你在把_recipeTypeButtons抽成独立类的时候踩了两个常见的小坑,才导致了这个TypeError: null: type 'Null' is not a subtype of type '(dynamic) => dynamic'错误,我来帮你一步步捋清楚问题和解决办法。

问题根源分析

1. 子组件构造函数的参数定义错误

你在RecipeTypeButtons的构造函数里写了required this.onPressed(filter),这是完全错误的写法——函数类型的参数只需要声明类型,不需要加括号和参数名。

2. 父组件传递onPressed参数的方式错误

你现在传的是onPressed: _updateFilterText(mealTypeFilter),这相当于直接执行了_updateFilterText函数,而这个函数是void类型(没有返回值),所以传递给子组件的是null。但子组件期望的是一个能接收字符串参数的函数,自然就触发了类型不匹配的错误。

修正后的完整代码

第一步:修复RecipeTypeButtons类

class RecipeTypeButtons extends StatelessWidget {
  // 明确声明函数类型:接收String参数,无返回值
  final void Function(String) onPressed;
  // 注:如果这个filter参数在子组件里没用到,可以直接移除,减少冗余
  final String filter;

  const RecipeTypeButtons({
    super.key,
    required this.onPressed, // 直接绑定参数,不要加括号和参数
    required this.filter,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.only(left: 20, right: 20, top: 20),
      child: SizedBox(
        height: MediaQuery.sizeOf(context).height * 0.05,
        child: ListView(
          scrollDirection: Axis.horizontal,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5.0),
              child: FilledButton(
                onPressed: () {
                  onPressed(""); // 调用父组件传过来的函数,传递对应筛选值
                },
                child: const Text('All'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5.0),
              child: FilledButton(
                onPressed: () {
                  onPressed("snack"); // 同理传递筛选值
                },
                child: const Text('snack'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

第二步:修复父组件调用子组件的代码

// 在_RecipeListState的build方法中修改
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Recipe book'),
      centerTitle: true,
      automaticallyImplyLeading: false,
    ),
    body: Column(
      children: [
        RecipeTypeButtons(
          // 直接传递函数本身,而不是执行函数
          onPressed: _updateFilterText,
          filter: mealTypeFilter,
        ),
        _recipesList(), // 保留原有的列表组件
      ],
    ),
  );
}

可选:给_updateFilterText添加类型注解(更规范)

// 明确参数类型为String,返回值为void
void _updateFilterText(String val) {
  setState(() {
    mealTypeFilter = val;
    futureRecipe = RecipeDataService().getRecipes(mealTypeFilter);
  });
}

额外小提示

看你的RecipeTypeButtons代码里,filter参数其实并没有被使用到,如果确实用不上,建议直接从构造函数里移除,避免传递不必要的参数,让代码更简洁。


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:22:59