在 flutter 中显示带有延迟加载的空列表小部件
Show empty list widget with lazy loading in flutter
这是我的代码,它有一个列表视图,我正在从 api 中获取数据,计数为 10。当我滚动并且列表为空时,我想显示空的列表小部件,但在我的例子中尽快当我得到空结果时,它显示空的小部件,但整个列表消失了。或者 Emplty 列表小部件替换列表视图。
请帮我修复一下。
class ReportVideoVerification extends StatefulWidget {
final AdminUserDetails userDetails;
final String title;
const ReportVideoVerification({Key key, this.title, this.userDetails}) : super(key: key);
@override
_ReportVideoVerificationState createState() => _ReportVideoVerificationState();
}
class _ReportVideoVerificationState extends State<ReportVideoVerification> {
TextEditingController fromDateController = TextEditingController();
TextEditingController toDateController = TextEditingController();
TextEditingController textController = TextEditingController();
String fromDate = "",
toDate = "";
int limit = Consts.limit;
static int page = 0; //offset
ScrollController _sc = new ScrollController();
bool isLoading = false;
List<VideoVerificationReportResult> _vvList = new List();
List<VideoVerificationReportResult> _filteredVvList;
Future<VideoVerificationReport> _videoVerificationReportResponse;
@override
void initState() {
print('init');
resetFilter();
super.initState();
_sc.addListener(() {
if (_sc.position.pixels == _sc.position.maxScrollExtent) {
getVideoReportData(page);
}
});
}
@override
void dispose() {
print('disposes');
page = 0;
_sc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(
title: (widget.title != null && widget.title.isNotEmpty)
? widget.title
: "Video Verification Reports",
actions: [
AppBarLogo(),
],
),
body: Column(children: [
_searchWidget(),
VerticalSpacing(5.0),
Expanded(
child: FutureBuilder<VideoVerificationReport>(
future: _videoVerificationReportResponse,
builder: (BuildContext context,
AsyncSnapshot<VideoVerificationReport> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.result != null &&
snapshot.data.result.length != 0) {
return _buildList();
}
else
{ return EmptyListWidget() ; }
} else {
return Center(child: LoadingIndicatorWidget());
}
}))
]),
resizeToAvoidBottomInset: false,
);
}
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isLoading ? 1.0 : 00,
child: new CircularProgressIndicator(),
),
),
);
}
Widget _buildList() {
int itemCount = _filteredVvList != null
? _filteredVvList.length
: _vvList.length + 1;
return
ListView.builder(
itemCount: itemCount, // Add one more item for progress indicator
padding: EdgeInsets.symmetric(vertical: 8.0),
itemBuilder: (BuildContext context, int index) {
if (index == _vvList.length) {
return _buildProgressIndicator();
} else {
return Column(
children: <Widget>[
Card(
//list data
),
if (index == _vvList.length - 1 && isLoading == false)
WidgetHelper.getLoaderEndText(context)
],
);
}
},
controller: _sc,
);
}
Future<VideoVerificationReport> getProjectDetails() async {
var result = await videoVerificationReportRequest(
context,
widget.userDetails.result.raLoginId,
limit.toString(),
page.toString(),
fromDate,
toDate);
return result;
}
getVideoReportData(int index) async {
if (!isLoading) {
if (this.mounted) {
setState(() {
isLoading = true;
});
}
print('value of page:' + page.toString());
try {
_videoVerificationReportResponse = getProjectDetails();
_videoVerificationReportResponse.then((response) {
if (response != null) {
List<VideoVerificationReportResult> result = new List();
if (response.result != null) {
print(response.success.toString());
if (response.success == true) {
result = response.result;
} else {
raisedToast(context, Consts.API_Msg_no_record, true, null);
}
}
if (this.mounted) {
setState(() {
isLoading = false;
if (response.result != null && response.result.length > 0) {
_vvList.addAll(result);
}
page = page + limit;
});
}
}
});
} on Error catch (e) {
print('error::: connectTimeout' + e.toString());
}
}
}
}
我的空小部件:
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 30),
child: Card(
child: ListTile(
title: Column(
children: <Widget>[
Icon(
Icons.tag_faces,
color: Theme.of(context).primaryColor,
size: 35.0,
),
SizedBox(
height: 5.0,
),
Text(
"No Record Found",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0, color: Colors.black87),
),
],
),
),
),
);
}
您可以像这样从此部分删除 length != 0
条件
if (snapshot.data.result != null) {
return _buildList();
} else {
return EmptyListWidget();
}
而是像这样在 _buildList()
中处理它
int itemCount = _filteredVvList != null
? _filteredVvList.length
: _vvList.length != 0 ? _vvList.length + 1 : 0;
当没有更多数据时这么说,你可以像这样有一个bool
bool noMoreData = false;
并在此处将其更改为true
if (response.result != null) {
if (response.result.length > 0)
_vvList.addAll(result);
else
noMoreData = true;
}
并像这样在 buildList()
中使用它
if (index == _vvList.length) {
return noMoreData ? EmptyListWidget() : _buildProgressIndicator();
}
这是我的代码,它有一个列表视图,我正在从 api 中获取数据,计数为 10。当我滚动并且列表为空时,我想显示空的列表小部件,但在我的例子中尽快当我得到空结果时,它显示空的小部件,但整个列表消失了。或者 Emplty 列表小部件替换列表视图。 请帮我修复一下。
class ReportVideoVerification extends StatefulWidget {
final AdminUserDetails userDetails;
final String title;
const ReportVideoVerification({Key key, this.title, this.userDetails}) : super(key: key);
@override
_ReportVideoVerificationState createState() => _ReportVideoVerificationState();
}
class _ReportVideoVerificationState extends State<ReportVideoVerification> {
TextEditingController fromDateController = TextEditingController();
TextEditingController toDateController = TextEditingController();
TextEditingController textController = TextEditingController();
String fromDate = "",
toDate = "";
int limit = Consts.limit;
static int page = 0; //offset
ScrollController _sc = new ScrollController();
bool isLoading = false;
List<VideoVerificationReportResult> _vvList = new List();
List<VideoVerificationReportResult> _filteredVvList;
Future<VideoVerificationReport> _videoVerificationReportResponse;
@override
void initState() {
print('init');
resetFilter();
super.initState();
_sc.addListener(() {
if (_sc.position.pixels == _sc.position.maxScrollExtent) {
getVideoReportData(page);
}
});
}
@override
void dispose() {
print('disposes');
page = 0;
_sc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget(
title: (widget.title != null && widget.title.isNotEmpty)
? widget.title
: "Video Verification Reports",
actions: [
AppBarLogo(),
],
),
body: Column(children: [
_searchWidget(),
VerticalSpacing(5.0),
Expanded(
child: FutureBuilder<VideoVerificationReport>(
future: _videoVerificationReportResponse,
builder: (BuildContext context,
AsyncSnapshot<VideoVerificationReport> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.result != null &&
snapshot.data.result.length != 0) {
return _buildList();
}
else
{ return EmptyListWidget() ; }
} else {
return Center(child: LoadingIndicatorWidget());
}
}))
]),
resizeToAvoidBottomInset: false,
);
}
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isLoading ? 1.0 : 00,
child: new CircularProgressIndicator(),
),
),
);
}
Widget _buildList() {
int itemCount = _filteredVvList != null
? _filteredVvList.length
: _vvList.length + 1;
return
ListView.builder(
itemCount: itemCount, // Add one more item for progress indicator
padding: EdgeInsets.symmetric(vertical: 8.0),
itemBuilder: (BuildContext context, int index) {
if (index == _vvList.length) {
return _buildProgressIndicator();
} else {
return Column(
children: <Widget>[
Card(
//list data
),
if (index == _vvList.length - 1 && isLoading == false)
WidgetHelper.getLoaderEndText(context)
],
);
}
},
controller: _sc,
);
}
Future<VideoVerificationReport> getProjectDetails() async {
var result = await videoVerificationReportRequest(
context,
widget.userDetails.result.raLoginId,
limit.toString(),
page.toString(),
fromDate,
toDate);
return result;
}
getVideoReportData(int index) async {
if (!isLoading) {
if (this.mounted) {
setState(() {
isLoading = true;
});
}
print('value of page:' + page.toString());
try {
_videoVerificationReportResponse = getProjectDetails();
_videoVerificationReportResponse.then((response) {
if (response != null) {
List<VideoVerificationReportResult> result = new List();
if (response.result != null) {
print(response.success.toString());
if (response.success == true) {
result = response.result;
} else {
raisedToast(context, Consts.API_Msg_no_record, true, null);
}
}
if (this.mounted) {
setState(() {
isLoading = false;
if (response.result != null && response.result.length > 0) {
_vvList.addAll(result);
}
page = page + limit;
});
}
}
});
} on Error catch (e) {
print('error::: connectTimeout' + e.toString());
}
}
}
}
我的空小部件:
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 30),
child: Card(
child: ListTile(
title: Column(
children: <Widget>[
Icon(
Icons.tag_faces,
color: Theme.of(context).primaryColor,
size: 35.0,
),
SizedBox(
height: 5.0,
),
Text(
"No Record Found",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0, color: Colors.black87),
),
],
),
),
),
);
}
您可以像这样从此部分删除 length != 0
条件
if (snapshot.data.result != null) {
return _buildList();
} else {
return EmptyListWidget();
}
而是像这样在 _buildList()
中处理它
int itemCount = _filteredVvList != null
? _filteredVvList.length
: _vvList.length != 0 ? _vvList.length + 1 : 0;
当没有更多数据时这么说,你可以像这样有一个bool
bool noMoreData = false;
并在此处将其更改为true
if (response.result != null) {
if (response.result.length > 0)
_vvList.addAll(result);
else
noMoreData = true;
}
并像这样在 buildList()
中使用它
if (index == _vvList.length) {
return noMoreData ? EmptyListWidget() : _buildProgressIndicator();
}