今天刷Flutter社区的时候,碰巧看到了一个这样的问题,回想了一下自己最近一个月也遇到不少关于setState无效的问题,请教了下同事,果然姜还是老的辣,哈哈~
(温馨提示:由于本人文笔欠佳和涉世尚浅,如果你理解不了的话,请尝试一下自己打断点操作,这真的对理解很有帮助)
引入问题: link.
(以上链接就是别人的问题,此处就不另外把问题描述一遍了,大家从上面链接查看原问题把!)
原因:
父widget用到子widget时,第一次使用时,会执行子widget中声明的构造函数,之后就不会执行了,但是子widget的build还是会执行的。最好的测试方法就是打断点,见图:
解说断点测试:
打完下面三个断点,运行代码,我们知道每次界面渲染的时候,是渲染1次Row,然后5次带不同参数的GameTabs,循环如此。设置断点后按F9执行下一步,会发现,三个断点的执行情况是1-2-3-2-3-2-3-2-3-2-3–>1-3-3-3-3-3–>1-3-3-3-3-3…,也就是说除了第一次渲染的时候,对active重新赋了值,之后setState重构界面时,用的还是之前的active。
解决方案:
细心的小伙伴已经发现我将
if (active) {
return ActiveGameTabs(title);
}
修改为
if (widget.active) {
return ActiveGameTabs(title);
}
目的是使得build子组件的时候,我们使用的是GameTabs这个widget的active,每次重构的时候GameTabs构造方法会被调用,但是_GameTabsState构造方法不会被调用,和widget的状态有关系(StatefulWidget与State)。
修改:
针对他人的代码略做了点改动
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:ui';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
List<bool> tabsActive = [true,false,false,false,false];
class _MyHomePageState extends State<MyHomePage> {
void changeTabs(int view) {
print("change");
print("view:$view");
for(int i = 0;i < tabsActive.length;i++) {
tabsActive[i] = false;
}
setState(() {
tabsActive[view-1] = true;
});
print(tabsActive);
}
@override
Widget build(BuildContext context) {
// print("build2");
return Scaffold(
body:Container(
// padding: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top),
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
GameTabs("tab1",1,tabsActive[0],changeTabs).featureView(),
GameTabs("tab2",2,tabsActive[1],changeTabs).featureView(),
GameTabs("tab3",3,tabsActive[2],changeTabs).featureView(),
GameTabs("tab4",4,tabsActive[3],changeTabs).featureView(),
GameTabs("tab5",5,tabsActive[4],changeTabs).featureView(),
],
),
)
);
print(tabsActive[3]);
}
}
typedef CallIntFun = void Function(int);
class GameTabs {
final String title;
final int view;
final bool active;
final CallIntFun changeTabs;
GameTabs(this.title,this.view,this.active,this.changeTabs);
Widget featureView() {
return Expanded(
child: GestureDetector(
onTap: (){
changeTabs(view);
},
child: Container(
height: 56,
padding: EdgeInsets.fromLTRB(0, 6, 0, 0),
decoration: BoxDecoration(
color: active ? Colors.white : Color.fromRGBO(235, 235, 235, 1),
border: Border.all(
color: Colors.green,
width: 3.0,
style: BorderStyle.none
),
),
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
),
),
),
)
);
}
}
欢迎提问和纠错哈~❤