Flutter ListView添加好友按钮点击后全局加载异常问题
问题分析
你用了**单个全局布尔值isLoading**控制所有添加按钮的状态。点击任意按钮时,这个变量被设为true,所有按钮都会读取这个值并切换到加载状态,导致全量按钮显示加载的问题。
解决步骤
把单个isLoading改成按用户uid记录加载状态的集合,用Set<String>存储正在加载的用户uid,精准控制单个按钮的状态:
1. 替换状态变量
在你的State类中,把原来的bool isLoading = false;替换成:
Set<String> loadingUserIds = {};
2. 修改按钮点击逻辑
点击时仅标记当前用户的uid为加载状态,请求完成(成功/失败)后移除该标记:
onTap: () { final targetUid = client["uid"]; setState(() { loadingUserIds.add(targetUid); }); PalRequestModel palRequest = PalRequestModel( name: ap.userModel.name, avatar: ap.userModel.avatar, phoneNumber: ap.userModel.phoneNumber, uid: ap.userModel.uid, ); ap.sendRequestToPals( context: context, palRequests: palRequest, palId: targetUid, onSuccess: () { setState(() { loadingUserIds.remove(targetUid); }); }, // 补充错误回调,避免加载状态一直卡住 onError: (error) { setState(() { loadingUserIds.remove(targetUid); }); } ); },
3. 修改按钮状态判断
将原来的isLoading判断,改成检查当前用户uid是否在loadingUserIds集合中:
child: loadingUserIds.contains(client["uid"]) ? Padding( padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ CustomProgressBar(), ], ), ) : Row( mainAxisSize: MainAxisSize.min, children: const [ Icon( Icons.person_add, size: 20, ), SizedBox( width: 5, ), Text( "add", style: TextStyle(fontSize: 18), ), ], ),
完整核心代码片段
// State类内定义状态变量 Set<String> loadingUserIds = {}; // StreamBuilder内的循环构建部分 for (var client in clients!) { final clientWidget = Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ ListTile( leading: FadedScaleAnimation( child: CircleAvatar( radius: 30.0, backgroundImage: Image.network(client["avatar"] ?? "https://i.pravatar.cc/300") .image), ), trailing: GestureDetector( onTap: () { final targetUid = client["uid"]; setState(() { loadingUserIds.add(targetUid); }); PalRequestModel palRequest = PalRequestModel( name: ap.userModel.name, avatar: ap.userModel.avatar, phoneNumber: ap.userModel.phoneNumber, uid: ap.userModel.uid, ); ap.sendRequestToPals( context: context, palRequests: palRequest, palId: targetUid, onSuccess: () { setState(() { loadingUserIds.remove(targetUid); }); }, onError: (error) { setState(() { loadingUserIds.remove(targetUid); }); }); }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(40), border: Border.all(width: 0.8, color: Colors.grey)), child: loadingUserIds.contains(client["uid"]) ? Padding( padding: const EdgeInsets.symmetric( vertical: 5.0, horizontal: 10.0), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ CustomProgressBar(), ], ), ) : Row( mainAxisSize: MainAxisSize.min, children: const [ Icon( Icons.person_add, size: 20, ), SizedBox( width: 5, ), Text( "add", style: TextStyle(fontSize: 18), ), ], )), ), title: Text( "${client["name"]}".toLowerCase(), overflow: TextOverflow.ellipsis, style: TextStyles.h2, ), subtitle: Text( "${client["bio"]}".toLowerCase(), overflow: TextOverflow.ellipsis, style: TextStyles.bodyText, ), ), Divider( height: 0.1, thickness: 0.5, endIndent: 10, indent: 10, color: ApplicationColors.offWhite, ), ], ); clientWidgets.add(clientWidget); }
注意事项
- 必须在请求失败的回调中也移除uid,避免因网络问题导致加载状态一直无法清除。
- 如果你的
sendRequestToPals方法没有错误回调,建议补充实现,或者用try/catch包裹请求逻辑。
内容的提问来源于stack exchange,提问作者sultanshah rajguru
相关产品推荐
相关产品推荐

