Flutter对接Laravel API时Visibility与initState相关异常求助
问题根因
- 你在
initState中同时启动了两个未做同步依赖的异步方法_getAuthenticatedUser和_getAllProducts,两个方法的执行完成顺序不可控 - 当数据库无产品时,
_getAllProducts接口返回的result是空数组,forEach遍历逻辑不会执行,内部的setState也就不会触发,此时_getAuthenticatedUser修改完widget.client后没有触发页面重绘,UI层Visibility组件读取的还是初始的false值 - 当数据库有产品时,
_getAllProducts的forEach会执行到内部的setState,触发页面重绘,此时widget.client已经完成赋值,所以显示正常
注意:直接修改widget的属性值不是Flutter的推荐做法,widget的属性应该是不可变的,建议把相关状态放到State类中管理
修复方案
方案1:控制异步执行顺序
调整初始化逻辑,等待用户权限信息加载完成后主动触发重绘,再加载产品数据,保证权限状态先更新:
@override void initState(){ super.initState(); _initData(); } // 统一初始化方法,控制异步执行顺序 _initData() async { // 先加载用户信息 await _getAuthenticatedUser(); // 加载完用户信息后主动触发重绘,更新权限相关UI setState(() {}); // 再加载产品数据 await _getAllProducts(); }
方案2:优化状态管理(更推荐)
把client、superAdmin、admin这些权限状态从widget属性移到当前State类中,修改状态后主动触发setState,避免直接修改widget属性:
// State类中定义内部状态 bool client = false; bool superAdmin = false; bool admin = false; String? photo; String? name; _getAuthenticatedUser() async { SharedPreferences _prefs = await SharedPreferences.getInstance(); var log = Logger(); var x = _prefs.getString('photoUser'); photo = json.decode(x); name = json.decode(_prefs.getString('Username') ?? '""'); if(_prefs.getString('token')!=null){ String role = json.decode(_prefs.getString('role') ?? '""'); superAdmin = role == 'superAdmin'; admin = role == 'admin'; if(role == 'user'){ _prefs.setString('client', 'client'); client = true; }else{ client = false; log.d('here not client'); } }else{ superAdmin = false; admin = false; client = false; } // 修改完状态后主动触发重绘 setState(() {}); } // 构建方法中直接使用State内的client变量 Visibility( visible: client, child: ListTile( leading: Icon(Icons.category,color: Colors.white,), title: Text('Produits refusé',style: TextStyle(color: Colors.white)), onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => RefusedProducts(_refusedProductList,client,photo,name))); } ), ),
内容的提问来源于stack exchange,提问作者devtest
相关产品推荐
相关产品推荐

