Flutter中直接在State类调用函数与在initState()中调用的区别
Flutter中State类成员直接初始化与initState中初始化的区别
在Flutter开发里,StatefulWidget对应的State类中,两种初始化成员变量的方式看似结果一样,但底层执行逻辑和适用场景有不少区别,具体如下:
1. 执行时机不同
- 直接初始化:比如示例里的
var info = getData();,这行代码在State实例被创建的瞬间就会执行,比initState()的执行时间更早。此时State还没和Widget树绑定,整个初始化过程是同步阻塞的。 - initState初始化:
info = getData();写在initState()里,会在State实例创建完成后、第一次调用build()之前执行,属于生命周期的固定环节。
2. Context和Widget参数的可用性差异
- 直接初始化:这个阶段State的
context还没初始化完成,同时widget对象也未必完全就绪。如果getData()函数里需要用到context(比如获取当前主题、屏幕尺寸),或者需要访问widget的参数,直接初始化会直接抛出异常。 - initState初始化:到这个阶段,State已经和Widget树完成绑定,
context和widget都可以安全调用,不用担心未初始化的问题。
3. 执行次数与性能影响
- 直接初始化:只要State实例被重新创建(比如父Widget重建、Widget的key发生变化),这个初始化逻辑就会重新执行一次。如果
getData()是耗时操作(比如网络请求、复杂计算),会多次阻塞页面初始化,影响性能。 - initState初始化:在整个State的生命周期里只会执行一次,哪怕后续因为状态变化触发多次
build(),也不会重复执行getData()。如果是异步初始化操作(比如网络请求),也适合在这里启动(记得在dispose()里做资源清理,避免内存泄漏)。
示例代码对比
data.dart文件
List<Map<String, dynamic>> getData() => [ {"name" : "osama", "desc": "hello osama", "sal": 1000}, {"name" : "ali", "desc": "hello ali", "sal": 800}, {"name" : "ahmed", "desc": "hello ahmed", "sal": 600}, ];
写法一:直接初始化成员变量
import 'package:column_app/data.dart'; import 'package:flutter/material.dart'; void main() => runApp(const MaterialApp(home: Info(),)); class Info extends StatefulWidget { const Info({Key? key}) : super(key: key); @override State<Info> createState() => InfoState(); } class InfoState extends State<Info> { var info = getData(); @override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: info.length, itemBuilder: (context, index) { return Center( child: Padding( padding: const EdgeInsets.all(100), child: ListTile( title: Text(info[index]['name'].toString()), subtitle: Text(info[index]['desc'].toString()), leading: Text(info[index]['sal'].toString()), ) ), ); }, ), ); } }
写法二:在initState中初始化
import 'package:column_app/data.dart'; import 'package:flutter/material.dart'; void main() => runApp(const MaterialApp(home: Info(),)); class Info extends StatefulWidget { const Info({Key? key}) : super(key: key); @override State<Info> createState() => InfoState(); } class InfoState extends State<Info> { var info; @override void initState() { info = getData(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: info.length, itemBuilder: (context, index) { return Center( child: Padding( padding: const EdgeInsets.all(100), child: ListTile( title: Text(info[index]['name'].toString()), subtitle: Text(info[index]['desc'].toString()), leading: Text(info[index]['sal'].toString()), ) ), ); }, ), ); } }
在你给出的示例里,getData()只是返回静态数据,两种写法看起来效果一致,但如果后续getData()需要扩展(比如加入依赖context的逻辑、异步请求),写法一就会出现问题,写法二更符合Flutter的生命周期规范。
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

