状态管理final
大约 2 分钟flutter
概述
有状态组件在状态类 class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin {...} 下的成员变量都是状态,不可直接赋值。如果为测试用可在声明成员变量时通过 final 为其设置立即数,有包裹状态的成员变量时通过 late 声明外层成员变量来防止 IDE 报错。对于 flutter 设计理念不清楚的话要先看 flutter 团队的设计理念 关注点分离
案例
下面代码在状态类 _HomeState 中为成员变量设置了立即数,所以前面使用了 final。成员变量 bannerList 需要包含 banner01 ,所以要声明前者为 late,同理的也要使用关键字 late 声明 homeModel。由此可见 flutter 在初始化 widget 时只为了初始化 UI,而不会初始化状态(成员变量),即此时还没有为成员变量分配内存空间,自然无法为其赋值(自己的理解)。
class Home extends StatefulWidget {
static HomeConfig? homeConfig;
const Home({super.key});
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin {
final HomeConfig config = HomeConfig.fromJson({'searchUrl':'https://D%AE%E7%B1%BB%E5%9E%8B.html'});
final CommonModel banner01 = CommonModel.fromJson({'icon':'https://xdfzn.png','title':'第一个banner','url':'www.baidu.com'});
final CommonModel banner02 = CommonModel.fromJson({'icon':'https://xdfznhanner02.png','title':'第二个banner','url':'www.sina.com.cn'});
final CommonModel banner03 = CommonModel.fromJson({'icon':'hts://o.1e.webp','title':'第三个banner','url':'https://jueji7288485'});
final CommonModel banner04 = CommonModel.fromJson({'icon':'https://.png','title':'第四个banner','url':'https://www.moxfaafd59'});
final CommonModel banner05 = CommonModel.fromJson({'icon':'https://xdfznh.nner03.png','title':'第五个banner','url':'https://www.geekailab.com/io/tools/json-to-dart/'});
late List<CommonModel> bannerList = [banner01,banner02,banner03,banner04,banner05];
late HomeModel homeModel = HomeModel.fromJson({
'config':config,'bannerList':bannerList
});
再来看一个例子,有状态 widget 中的 state 类中有私有成员方法 _reqData,
class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin {
HomeModel homeModel = _reqData();
_reqData() async {
HomeModel data = await HomeDao.fetch();
setState(() {
homeModel = data;
});
}
}
在状态类 _HomeState 中直接调用时会报错:
The instance member '_reqData' can't be accessed in an initializer
可以看出有状态 widget 在初始化时会执行状态类 _HomeState 的代码来构建 UI,此时还没有实例化 状态类,因此其中的成员方法 _reqData 无法被调用,导致如上报错。正常的做法如下
class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin {
HomeModel? homeModel;
void initState(){
super.initState();
_reqData();
}
void _reqData() async {
//TODO: 请求数据后使用 setState(){...} 初始化状态成员变量
HomeModel data = await HomeDao.fetch();
setState(() {
homeModel = data;
});
}
}
