Flutter中如何通过字符串名称调用对应Widget避免大量if-else判断
实现方案
Dart/Flutter环境下禁用了反射库dart:mirrors,因此无法通过字符串直接实例化对应类,最推荐的方案是用静态映射表实现匹配,全程不需要写任何分支判断,维护成本极低。
方案1:单独维护映射表
首先全局定义模板名称和对应Widget构造函数的映射关系:
// 全局映射表,新增模板仅需要在此处添加一行映射即可 final Map<String, Widget Function()> templateBuilderMap = { 'Temp_1': () => const Temp_1(), 'Temp_2': () => const Temp_2(), 'Temp_3': () => const Temp_3(), 'Temp_4': () => const Temp_4(), };
使用时直接根据TemplateModel的name字段取值,建议增加容错处理避免空异常:
Container( // 找不到对应模板时返回空占位组件,可替换为自定义的错误提示组件 child: templateBuilderMap[yourTemplate.name]?.call() ?? const SizedBox.shrink(), )
方案2:将构造函数内置到TemplateModel中
如果希望只维护一份模板列表,不需要额外维护映射表,可以直接修改TemplateModel的定义,将构造函数作为参数传入:
class TemplateModel { final int id; final String name; final String previewBack; final String previewFront; // 新增Widget构造函数字段 final Widget Function() widgetBuilder; const TemplateModel({ required this.id, required this.name, required this.previewBack, required this.previewFront, required this.widgetBuilder, }); }
定义模板列表时直接传入对应构造函数:
List<TemplateModel> listTemplate = [ TemplateModel( id: 1, name: 'Temp_1', previewBack: AppImages.TEMP_1, previewFront: AppImages.TEMP_1, widgetBuilder: () => const Temp_1(), ), TemplateModel( id: 2, name: 'Temp_2', previewBack: AppImages.TEMP_2, previewFront: AppImages.TEMP_2, widgetBuilder: () => const Temp_2(), ), // 后续新增模板仅需在此处添加一条配置即可 ];
使用时直接调用构造函数即可:
Container( child: yourTemplate.widgetBuilder(), )
两种方案的性能都和直接调用构造函数一致,没有额外开销,哪怕模板数量过百也可以高效维护。
内容的提问来源于stack exchange,提问作者Michel Lacal
相关产品推荐
相关产品推荐

