我已经调用post类型的api,以使用FutureBuilder在ListView上异步加载数据,但它只调用了一次,我想在ListView上显示无限的数据加载。
缺少添加FutureBuilder或ListView的某些属性的方法。
有人可以帮我解决这个问题吗,我是新来的。
我正在使用状态控件来实现此功能。
请参考以下代码,
import 'package:flutter/material.dart';
import 'package:testlistviewlazyload/Utils.dart';
import 'package:testlistviewlazyload/ServiceManager.dart';
import 'package:testlistviewlazyload/Constant.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class ClassHome extends StatefulWidget {
@override
stateClassHome createState() => stateClassHome();
}
class stateClassHome extends State<ClassHome> {
bool isLoading = false;
List<dynamic> arrayFoodList = List<dynamic>();
@override
void initState() {
super.initState();
}
Future<List<dynamic>> funcLoadMore() async{
var dicArguments = {'restaurant_id': '3',
'menu_id': '0',
'offset': '0'
};
final dictResponse = await ServiceManager().callWebservice(
enumMethodType.POST, ConstantApi.keyRestaurantMenuFoodList,
dicArguments, {
'Authorization':
await Utils().funcGetSession(ConstantSession.keyAuthToken)
}, 'tagRestaurantMenuFoodList');
if (dictResponse['error'] == false) {
if (dictResponse['mainResponse']['error'] == false) {
return dictResponse['mainResponse']['data']['food_items']
as List<dynamic>;
} else {
Utils()
.funcDisplayAlertView(
'', "${dictResponse['message']}", context);
}
} else {
Utils().funcDisplayAlertView(
'', "${dictResponse['message']}", context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('hello')),
body: Container(
color: Colors.pink[50],
child: Column(
children: <Widget>[
Expanded(
child: FutureBuilder<List<dynamic>>(
future: funcLoadMore(), // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
List<dynamic> arrayTest = snapshot.data ?? [];
return Scrollbar(
child: ListView.builder(
itemCount: arrayTest.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(arrayTest[index]['name']),
);
},
)
);
},
),
),
Container(
height: isLoading ? 50.0 : 0,
color: Colors.white,
child: Center(
child: new CircularProgressIndicator(),
),
),
],
),
)
);
}
}
答案 0 :(得分:3)
您可以使用Stream代替Future。这是一个通用示例,带有一个缓存和一个scrollController
,当用户位于底部页面时,该class _PageState extends State<Page> {
int _count = 10;
int _limit = 0;
bool isLoading = false;
List<Item> _cachedItems = List.from([]);
StreamController<List<Item>> _streamController =
StreamController<List<Item>>();
StreamSink<List<Item>> get itemsSink => _streamController.sink;
Stream<List<Item>> get itemsStream => _streamController.stream;
ScrollController _scrollController = ScrollController();
Future<void> _addItems() async {
final params = {'count': '$_count', 'limit': '$_limit'};
try {
isLoading = true;
// Fetch newItems with http
isLoading = false;
_cachedItems.addAll(newItems);
itemsSink.add(_cachedItems);
_limit += 10;
} catch (e) {
itemsSink.addError(e);
}
}
_scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange &&
!isLoading) {
_addItems();
}
}
@override
void initState() {
_scrollController.addListener(_scrollListener);
super.initState();
}
@override
void didChangeDependencies() {
if (_cachedItems.isEmpty) _addItems();
super.didChangeDependencies();
}
@override
void dispose() {
_streamController.close();
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<List<Item>>(
stream: itemsStream,
builder: (context, snapshot) {
ListView(
controller: _scrollController,
/// Build here your ListView
),
}
),
);
}
}
会提取下一个项目:
{{1}}
答案 1 :(得分:0)
使用ScrollController异步加载数据非常容易,
import 'package:flutter/material.dart';
import 'package:testlistviewlazyload/Utils.dart';
import 'package:testlistviewlazyload/ServiceManager.dart';
import 'package:testlistviewlazyload/Constant.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class ClassHome extends StatefulWidget {
@override
stateClassHome createState() => stateClassHome();
}
class stateClassHome extends State<ClassHome> {
bool isLoading = false;
ScrollController scrollController = ScrollController();
List<dynamic> arrayFoodList = List<dynamic>();
int varLoadedRecordsCount = 0;
int varTotalRecords = 18;
@override
void initState() {
super.initState();
funcLoadMore();
scrollController.addListener((){
print('scroll controller called');
if(scrollController.position.maxScrollExtent == scrollController.offset){
if (varLoadedRecordsCount < varTotalRecords) {
funcLoadMore();
}
}
});
}
void funcLoadMore() async{
setState(() {
isLoading = true;
});
var dicArguments = {'restaurant_id': '3',
'menu_id': '0',
'offset': '${varLoadedRecordsCount}'
};
final dictResponse = await ServiceManager().callWebservice(
enumMethodType.POST, ConstantApi.keyRestaurantMenuFoodList,
dicArguments, {
'Authorization':
await Utils().funcGetSession(ConstantSession.keyAuthToken)
}, 'tagRestaurantMenuFoodList');
setState(() {
isLoading = false;
});
if (dictResponse['error'] == false) {
if (dictResponse['mainResponse']['error'] == false) {
print('response came');
arrayFoodList.addAll(dictResponse['mainResponse']['data']['food_items']
as List<dynamic>);
varLoadedRecordsCount += arrayFoodList.length;
// return dictResponse['mainResponse']['data']['food_items']
// as List<dynamic>;
} else {
Utils()
.funcDisplayAlertView(
'', "${dictResponse['message']}", context);
}
} else {
Utils().funcDisplayAlertView(
'', "${dictResponse['message']}", context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('hello')),
body: Container(
color: Colors.pink[50],
child: Column(
children: <Widget>[
Expanded(
child: Scrollbar(
child: ListView.builder(
controller: scrollController,
itemCount: arrayFoodList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('${arrayFoodList[index]['name']}'),
);
},
)
),
),
Container(
height: isLoading ? 50.0 : 0,
color: Colors.white,
child: Center(
child: new CircularProgressIndicator(),
),
),
],
),
)
);
}
}