如何无限滚动 Flutter 在 REST 分页与提供程序?



我创建了一个带有提供程序包的颤振项目 以前,在此示例项目之后,它使用ScopedModel运行良好。

我想以相同的逻辑实现 v3 提供程序,

//main.dart

@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(builder: (context) => NoteContentModel()),
],
...
home: NoteContentPage(),
),
);
}

note_content_model.dart


class NoteContentModel extends ChangeNotifier {
final _pageSize = 30;
List<Content> _content = [];
bool _isLoading = false;
int _totalResults;
int _totalPages;
bool _hasMorePages = true;
String _placeName;
bool _isLoadingMore = false;
// .. other setter getter
int getNoteCount() => _content.length;
Future<dynamic> _getData([int page = 1]) async {
var res = await http.get(getUrl(page));
return jsonDecode(res.body);
}
Future getNoteContent([int page = 1]) async {
if (page == 1) {
_isLoading = true;
_content.clear();
} else {
_isLoadingMore = true;
}
notifyListeners();
var responseData = await _getData();
List noteContent = responseData['content'];
noteContent.forEach((content) {
_content.add(Content.fromJson(content));
});
_totalResults = responseData['total_count'];
_totalPages = responseData['page_count'];
if (responseData['page_number'] == totalPages) {
_hasMorePages = false;
}
if (page == 1) {
_isLoading = false;
} else {
_isLoadingMore = false;
}
notifyListeners();
}
}

note_content_page.dart


class NoteContentPage extends StatefulWidget {
@override
_NoteContentPageState createState() => _NoteContentPageState();
}
class _NoteContentPageState extends State<NoteContentPage> {
int page = 1;
ScrollController controller;
void _scrollListener() {
final NoteContentModel noteModel = Provider.of<NoteContentModel>(context);
if (controller.position.pixels == controller.position.maxScrollExtent) {
if (!noteModel.isLoadingMore && noteModel.hasMorePages) {
page++;
print("Current page: $page");
noteModel.getNoteContent(page);
}
}
}
@override
void initState() {
super.initState();
controller = new ScrollController()..addListener(_scrollListener);
}
@override
void dispose() {
super.dispose();
controller.dispose();
}
@override
Widget build(BuildContext context) {
final NoteContentModel noteModel = Provider.of<NoteContentModel>(context);
// Call initiate first page
noteModel.getNoteContent(page);
return Scaffold(
appBar: AppBar(title: Text("Test")),
body: CustomScrollView(
controller: controller,
slivers: <Widget>[
noteModel.isLoading
? SliverFillRemaining(
child: Center(
child: CircularProgressIndicator(),
),
)
: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
if (index == noteModel.getNoteCount()) {
if (noteModel.hasMorePages) {
print("here1");
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Center(child: CircularProgressIndicator()),
);
}
return Container();
} else {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(noteModel.content[index].title),
// child: Text("test"),
),
],
);
}
},
childCount: noteModel.getNoteCount(),
),
)
],
),
);
}
}

我总是收到此消息循环markNeedsBuild() called during build结束跟踪错误

I/flutter ( 2525): ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
I/flutter ( 2525): The following assertion was thrown while dispatching notifications for NoteContentModel:
I/flutter ( 2525): setState() or markNeedsBuild() called during build.
I/flutter ( 2525): This ListenableProvider<NoteContentModel> widget cannot be marked as needing to build because the
...
I/flutter ( 2525): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3670:11)
I/flutter ( 2525): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3685:6)
I/flutter ( 2525): #2      State.setState (package:flutter/src/widgets/framework.dart:1161:14)
I/flutter ( 2525): #3      __BuilderListenableDelegate&BuilderStateDelegate&_ListenableDelegateMixin.startListening.<anonymous closure> (package:provider/src/listenable_provider.dart:186:36)
I/flutter ( 2525): #4      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:206:21)
I/flutter ( 2525): #5      NoteContentModel.getNoteContent (package:paging_provider/providers/note_content_model.dart:42:5)
I/flutter ( 2525): <asynchronous suspension>
I/flutter ( 2525): #6      _NoteContentPageState.build (package:paging_provider/pages/note_content_page.dart:44:15)
I/flutter ( 2525): #7      StatefulElement.build (package:flutter/src/widgets/framework.dart:4012:27)
I/flutter ( 2525): #8      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3924:15)
I/flutter ( 2525): #9      Element.rebuild (package:flutter/src/widgets/framework.dart:3721:5)
I/flutter ( 2525): #10     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3907:5)
...
// This trace always loop on app running
I/flutter ( 2525): Another exception was thrown: setState() or markNeedsBuild() called during build....

仅此而已,任何回应将不胜感激。

你必须将函数包装在addPostFrameCallback((中: 因此,调用是在构建函数完成工作并在屏幕上绘制小部件后提交的

//改变

noteModel.getNoteContent(page(;

//自

WidgetsBinding.instance.addPostFrameCallback((_( => noteModel.getNoteContent(page(; );

希望这个答案对某人有价值。

最新更新