Dart中如何获取Future的最终返回值?实现后取值为null求助
问题原因
- FutureBuilder使用逻辑错误:FutureBuilder是用于在Widget树中渲染异步数据的组件,不是用来处理异步回调的。你在builder中直接调用
setState会触发无限重绘(setState触发build,build再次执行FutureBuilder的builder逻辑,再次调用setState,陷入死循环)。同时你在FutureBuilder代码后同步打印、返回_isGidUnique时,异步请求还未执行完成,自然拿到的是初始值null。 - 查询逻辑性能极差:当前实现是拉取groups集合下的所有文档遍历匹配,当集合内数据量较大时,请求耗时、流量消耗都会非常高,完全没有必要。
解决方法
第一步:优化群组名校验方法
直接查询指定名称的文档是否存在即可,无需拉取全量数据:
Future<bool> isGroupNameAvailable(String name) async { final groupDoc = await _fireStore.collection("groups").doc(name).get(); return !groupDoc.exists; // 文档不存在说明名称可用,返回true }
第二步:调整校验触发逻辑
不要在build方法中执行校验逻辑,把触发时机放到用户输入的回调中,比如输入框的onChanged或者表单提交回调:
// 示例:绑定到TextField的onChanged回调 TextField( onChanged: (inputName) async { final isAvailable = await db!.isGroupNameAvailable(inputName); setState(() { _isGidUnique = isAvailable ? null : "该群组名称已被占用,请更换其他名称"; }); }, decoration: InputDecoration( errorText: _isGidUnique, // 其他输入框样式配置 ), // 其他输入框配置 )
补充:如果要使用FutureBuilder实现的正确写法
如果希望用FutureBuilder处理,可以直接在内部渲染错误提示,无需额外维护_isGidUnique变量,也不要在builder中调用setState:
FutureBuilder<bool>( future: db!.isGroupNameAvailable(inputValue), builder: (BuildContext context, AsyncSnapshot<bool> snap) { // 异步请求中显示加载提示 if (snap.connectionState == ConnectionState.waiting) { return const Text("校验中...", style: TextStyle(color: Colors.grey)); } // 名称已被占用显示错误提示 if (snap.hasData && !snap.data!) { return const Text("该群组名称已被占用,请更换其他名称", style: TextStyle(color: Colors.red)); } // 校验通过不显示额外内容 return const SizedBox.shrink(); }, )
内容的提问来源于stack exchange,提问作者Harel Moshayof
相关产品推荐
相关产品推荐

