我有一个小部件,它向一个API发出请求,API返回一个Map。我想做的是,每次加载小部件时,不要发出相同的请求,并将列表保存到appState.myList
。但是,当我在FutureBuilder
中执行appState.myList = snapshot.data;
时,我得到以下错误:
flutter: ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
flutter: The following assertion was thrown while dispatching notifications for MySchedule:
flutter: setState() or markNeedsBuild() called during build.
flutter: This ChangeNotifierProvider<MySchedule> widget cannot be marked as needing to build because the
flutter: framework is already in the process of building widgets. A widget can be marked as needing to be
flutter: built during the build phase only if one of its ancestors is currently building. ...
sun.dart
档案:
class Sun extends StatelessWidget {
Widget build(BuildContext context) {
final appState = Provider.of<MySchedule>(context);
var db = PostDB();
Widget listBuild(appState) {
final list = appState.myList;
return ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return ListTile(title: Text(list[index].title));
},
);
}
Widget futureBuild(appState) {
return FutureBuilder(
future: db.getPosts(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// appState.myList = snapshot.data;
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(title: Text(snapshot.data[index].title));
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Center(
child: CircularProgressIndicator(),
);
},
);
}
return Scaffold(
body: appState.myList != null
? listBuild(appState)
: futureBuild(appState));
}
}
postService.dart
档案:
class PostDB {
var isLoading = false;
Future<List<Postmodel>> getPosts() async {
isLoading = true;
final response =
await http.get("https://jsonplaceholder.typicode.com/posts");
if (response.statusCode == 200) {
isLoading = false;
return (json.decode(response.body) as List)
.map((data) => Postmodel.fromJson(data))
.toList();
} else {
throw Exception('Failed to load posts');
}
}
}
我知道myList
调用了notifyListeners()
,这就是导致错误的原因。希望我没有弄错。如果是这样,我如何设置appState.myList
并在应用程序中使用而不出现上述错误?
import 'package:flutter/foundation.dart';
import 'package:myflutter/models/post-model.dart';
class MySchedule with ChangeNotifier {
List<Postmodel> _myList;
List<Postmodel> get myList => _myList;
set myList(List<Postmodel> newValue) {
_myList = newValue;
notifyListeners();
}
}
4条答案
按热度按时间6qqygrtg1#
出现该异常的原因是,您正在从小部件的子代同步修改小部件。
这是不好的,因为它可能会导致不一致的部件树。一些部件可能是使用变异前的值构建的部件,而其他部件可能使用变异后的值。
解决方案是消除不一致性。使用
ChangeNotifierProvider
,通常有两种情况:ChangeNotifier
上执行的变异总是在与创建ChangeNotifier
的 build 相同的 build 中完成。在这种情况下,您可以直接从
ChangeNotifier
的构造函数进行调用:在这种情况下,你应该把你的突变 Package 在一个
addPostFrameCallback
或Future.microtask
中:3xiyfsfu2#
我在使用提供程序时遇到过类似的问题。我的解决方案是在获取数据时添加
WidgetsBinding.instance.addPostFrameCallback()
。ocebsuys3#
简单地从代码中删除
notifyListeners();
。我遇到了这个错误,这就是我解决这个问题所做的。w46czmvw4#
还有另一种方法可以解决这个问题,那就是在
Future
上使用StreamSubscription
。这将需要更多的样板代码,但它有助于确保其他逻辑可以被分离到小部件构建材料中,以防止副作用。第一个
请查看here中的完整示例代码。