FutureBuilder 与 Notifylistener 冲突
Posted
技术标签:
【中文标题】FutureBuilder 与 Notifylistener 冲突【英文标题】:FutureBuilder conflict with Notifylistener 【发布时间】:2021-10-23 17:08:15 【问题描述】:我的提供程序文件中有一个这样的方法来更新来自服务器的项目列表:
Future<void> getServerMeals(String userName, String date) async
final QueryBuilder<ParseObject> parseQuery =
QueryBuilder<ParseObject>(ParseObject('UsersEaten'));
parseQuery
..whereContains('eatenBy', userName)
..whereEqualTo('eatenDate', date);
final ParseResponse apiResponse = await parseQuery.query();
if (apiResponse.success && apiResponse.results != null)
List<dynamic>? apiRes = apiResponse.results;
List<dynamic> newMeals = apiRes!
.map((e) => EatenItem(
id: e['objectId'],
eatenCal: e['eatenCal'],
eatenTitle: e['eatenTitle'],
eatenImageUrl: e['eatenImg'],
userId: e['objectId'],
))
.toList();
_eatenMeals = newMeals;
print(apiResponse.results);
在我的主屏幕中,我将该列表包装到 FutureBuilder 中,它可以正常工作并返回一个列表:
Container(
height: MediaQuery.of(context).size.height * 0.6,
margin: EdgeInsets.only(left: 30, right: 30),
child: FutureBuilder(
builder: (ctx, snapshot)
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
return ListView.builder(
itemCount: mealsList.eatenMeals.length,
itemBuilder: (ctx, index) =>
DailyEaten(mealsList.eatenMeals[index]),
);
,
future: Provider.of<EatenMeals>(context)
.getServerMeals(currentUser.username, now),
),
),
但是当我在我的方法中添加 notifylistener() 时,我未来的构建器列表停留在等待状态并且不会更新列表这里出了什么问题
【问题讨论】:
【参考方案1】:@nvoigt
这是我的小部件,我已从构建方法中删除了这些提供程序
class TimelineWidget extends StatelessWidget
@override
Widget build(BuildContext context)
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: FutureBuilder(
future: Provider.of<EatenMeals>(context, listen: false).getServerMeals(),
builder: (ctx, snapshot)
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
return Consumer<EatenMeals>(
builder: (ctx, mealsList, child) => ListView.builder(
itemCount: mealsList.eatenMeals.length,
itemBuilder: (ctx, index) =>
DailyEaten(mealsList.eatenMeals[index]),
),
);
,
),
),
],
);
如您所见,我的构建方法中没有任何内容,并且我使用 Consumer 来避免此循环,但仍然构建方法正在重建,您能用代码 sn-ps 解释一下吗?我很感激
【讨论】:
"future: Provider.ofmyVariable = Provider.of<EatenMeals>(context, listen: false).getServerMeals()
放在 initState 或 didChangedepndencies 我应该如何在构建方法中获得 myVariable
值??
例如,通过使其成为您所在州的成员变量。这是与 FutureBuilder 一起使用的 Future 的一个小而完整的示例:***.com/questions/63017280/…【参考方案2】:
这是因为调用notifyListeners
将重建build
方法(您调用Provider.of...
的那个方法),这将创建一个循环。(build
方法调用未来,notifyListener
将重建build
方法,这个过程会一直持续下去)。
为防止这种情况,请为 of
方法提供另一个参数:listen: false
Provider.of<EatenMeals>(context, listen: false).getServerMeals(currentUser.username, now);
这将阻止build
方法重建。
【讨论】:
这是正确的,但解决方案是胶带“解决方案”。很多其他的事情都可以触发build方法,build方法需要固定,而不是provider。 连接状态仍然卡在等待中 @nvoigt 在我将 Future 移到构建方法之外后,您会告诉我我提供给未来构建器的“未来”参数吗?例如,当有人更改日期时,我想更新该列表,当数据发生更改时,我应该如何触发未来的构建器重建? 您在小部件状态中使用了 Future 类型的变量。例如:***.com/questions/63017280/… @nvoigt 请在下面阅读我的问题,我真的很困惑,我写了答案:【参考方案3】:问题是你在你的构建方法中创造你的未来。
这意味着在每次构建时,您再次创造这个未来。
这是您程序中的一个小麻烦和错误,直到您还添加未来本身触发重建,这意味着它将运行,触发重建,重建将等待一个 new 未来,它将运行,触发重建,再次创建一个 new 未来......你明白了。这是一个无限循环的运行未来,只是为了重建和运行它。
你必须创建你的未来在构建方法之外。 build 方法可以被多次触发。仅在您的构建方法中引用 Future 类型变量,并在另一个方法中分配该变量,可能是 init 或当有人单击按钮时在某些 setState 调用中。
【讨论】:
以上是关于FutureBuilder 与 Notifylistener 冲突的主要内容,如果未能解决你的问题,请参考以下文章
FutureBuilder 与 Notifylistener 冲突
6-3 异步:Future与FutureBuilder实用技巧
FlutterFutureBuilder 异步编程 ( FutureBuilder 构造方法 | AsyncSnapshot 异步计算 )