请观看此36 seconds
视频,以使其更加清晰,因为它解释起来太冗长:https://www.youtube.com/watch?v=W6WdQuLjrCs
应用程序结构->
Outer Page -> NoteList Page
外页代码:
class OuterPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return OuterPageState();
}
}
class OuterPageState extends State<OuterPage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int _selectedTab = 0;
var noteList;
final _pageOptions = [
NoteList(),
AnotherPageScreen(),
];
@override
Widget build(BuildContext context) {
var noteProvider = Provider.of<NotesProvider>(context, listen: false);
var customFabButton;
if (_selectedTab == 0) {
customFabButton = FloatingActionButton(
// Password section
onPressed: () {
navigateToDetail(context, Note('', '', 2), 'Add Note');
},
child: Icon(Icons.add),
);
~~~ SNIP ~~~
“注释”标签,也称为NoteList
页代码:
class NoteList extends StatefulWidget {
NoteList();
@override
NoteListState createState() => NoteListState();
}
class NoteListState extends State<NoteList> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
List<Note> noteList;
int count = 0;
@override
Widget build(BuildContext context) {
Provider.of<NotesProvider>(context).getNotes();
return Scaffold(
key: _scaffoldKey,
body: Provider.of<NotesProvider>(context).count > 0
? NoteListScreen(_scaffoldKey)
: CircularProgressIndicator());
}
}
有关完整代码:请在此处检查:https://github.com/LuD1161/notes_app/tree/reusable_components
我知道FutureBuilder
有可能的解决方案,但我认为甚至Provider
也适用于此用例。
而且这里是反模式吗?
另外,请不要为同一件事建议另一个软件包,如果可能的话,请尝试将解决方案限制为Provider
或基本库。
FutureBuilder
在这里不能使用,因为delete
中有一个list tile
按钮,因此,当笔记被删除时,note list
将不会得到更新。 / p>
答案 0 :(得分:0)
问题是由于您正在从build方法调用的getNotes函数引起的。您正在从该函数调用notifyListeners。再次重新构建窗口小部件,并再次调用build方法,此循环继续。
您要么需要将provider的listen属性设置为false,但是这会破坏您的功能。要解决此问题,您必须将getNotes调用从构建函数移至initState,如下所示:
@override
void initState() {
super.initState();
postInit(() {
Provider.of<NotesProvider>(context).getNotes();
});
}
实现postInit(参考:Flutter Issue 29515):
extension StateExtension<T extends StatefulWidget> on State<T> {
Stream waitForStateLoading() async* {
while (!mounted) {
yield false;
}
yield true;
}
Future<void> postInit(VoidCallback action) async {
await for (var isLoaded in waitForStateLoading()) {}
action();
}
}
注意:除了编写postInit代码外,您还可以出于相同目的使用after_init包。
其他一些讨论类似问题的帖子: