Flutter自定义文本组件运行时触发StackOverflow栈溢出报错
栈溢出根本原因定位
报错的触发点看起来指向Hometext组件,实际问题出在全局Data类的无限递归初始化逻辑,和Hometext本身的代码逻辑没有关系。
递归形成的完整逻辑链
当前代码里的Data是普通非单例类,在它的实例成员初始化阶段存在自调用构造的循环:
- 当Hometext的build方法第一次执行
Data().colorslist['black']时,会触发首次Data实例的创建流程 - 新的
Data实例开始按顺序初始化所有成员变量:先完成colorslist、pageviewdata等无依赖的成员初始化 - 初始化到
drawerlisttile列表时,每一个列表项的Icon配置都需要调用Data().colorslist['offwhite']来取色,这里的Data()会触发第二次、第三次……新的Data实例创建 - 每一次新创建的
Data实例都会重复上述初始化流程,直到栈内存被占满抛出StackOverflow错误,和看到的堆栈中Map反复初始化、rehash、插入键值的报错完全匹配。
彻底修复方案
- 将Data改为全局单例模式,避免无意义的实例重复创建,从结构上打破自调用循环
- 调整成员初始化顺序:不要在类的字段初始化阶段就调用类自身的构造方法取依赖值,把依赖
colorslist的drawerlisttile初始化挪到构造方法中执行,等基础配置初始化完成后再生成列表项 - 全项目把所有
Data()的调用替换为单例实例的取法,不再反复新建对象
修正后的参考代码
// 单例模式实现的全局配置类 class Data { // 私有构造,禁止外部直接new Data._internal(); // 全局唯一的实例入口 static final Data instance = Data._internal(); // 基础配置字段,无依赖优先初始化 final Map colorslist = { 'black': Color.fromRGBO(10, 9, 8, 1), 'darkgreen': Color.fromRGBO(34, 51, 59, 1), 'offwhite': Color.fromRGBO(234, 224, 213, 1), }; final List pageviewdata = [ 'lib/assets/pageview1.jpg', 'lib/assets/pageview2.jpg', 'lib/assets/pageview3.jpg', ]; final List pageviewnumbers = [0, 1, 2]; final List categories = [ Categories(name: 'Health&Beuty', image: 'lib/assets/health&beuty.jpg'), Categories(name: 'Books', image: 'lib/assets/books.jpg'), Categories(name: 'Fashion', image: 'lib/assets/fashion.jpg'), Categories(name: 'Electronics', image: 'lib/assets/electronics.jpg'), ]; // 声明依赖colorslist的字段,不在初始化阶段赋值 late final List<Drawerlisttile> drawerlisttile; // 构造方法中完成有依赖的字段初始化,彻底打破自调用循环 Data() { drawerlisttile = [ Drawerlisttile(name: 'Home', icon: Icon(Icons.home,color: colorslist['offwhite'])), Drawerlisttile(name: 'Cartlist', icon: Icon(Icons.shopping_cart,color: colorslist['offwhite'])), Drawerlisttile(name: 'Orders', icon: Icon(Icons.shopping_bag_rounded,color: colorslist['offwhite'])), Drawerlisttile(name: 'Settings', icon: Icon(Icons.settings,color: colorslist['offwhite'])), ]; } }
对应的Hometext组件里的取色代码,全部把Data()替换成Data.instance即可,比如Data.instance.colorslist['black']。
常见排查误区
不要把排查方向放到Hometext的布局逻辑上——这个组件只是刚好是项目里第一个触发Data实例化的位置,只要修复了Data类的递归初始化问题,哪怕你在别的组件里第一次调用Data,也不会再出现栈溢出。
内容的提问来源于stack exchange,提问作者Mahmoud Hegab
相关产品推荐
相关产品推荐

