如何在flutter中的build方法内部调用provider中的方法



我在类中有一个方法,该方法扩展了从API获取数据的changeNotifier。现在,每当在构建方法中打开页面时,我都想调用该方法,但当我调用该方法时,由于notifyListeners方法,它会被重复调用。我想知道如何只调用一次方法。

ReportProvider.dart

class ReportProvider extends ChangeNotifier
{
static DateFormat dateFormat = new DateFormat('dd-MM-yyyy');
static DateFormat actualDateFormat = new DateFormat("yyyy-MM-dd");
String _toDate = dateFormat.format(new DateTime.now());
String _actualToDate = actualDateFormat.format(new DateTime.now());
String _actualFromDate = actualDateFormat.format(new DateTime.now().subtract(new Duration(days: 7)));
String _fromDate = dateFormat.format(new DateTime.now().subtract(new Duration(days: 7)));
bool _progressStatuc = false;
bool _chartVisible = true;
bool _errorVisible = false;
String _errorMessage;
String get errorMessage => _errorMessage;
bool get errorVisible => _errorVisible;
bool get chartVisible => _chartVisible;
bool get progressStatus => _progressStatuc;
String get toDate => _toDate;
String get fromDate => _fromDate;
List<PieData> _data = new List();
List<PieData> get data => _data;
Future<void> getReportData() async
{
Map<String,dynamic> sessiondata = await new Utilities().getSessionData();
int shopid = sessiondata['shopid'];
Map<String,String> reportData = new Map();
reportData['shopid'] = shopid.toString();
reportData["fromdate"] = _actualFromDate;
reportData["todate"] = _actualToDate;
String token = await new Utilities().getToken();
Map userHeader = {"token": token};
print(reportData.toString());
if(await new Utilities().checkInternet())
{
try
{
http.Response response = await http.post(EndPointUrl.report,body: reportData,headers: userHeader);
String message = json.decode(response.body)['message'];
List<ReportData> data = json.decode(response.body)['data'];
data.forEach((reportData){
_data.add(new PieData(reportData.menuname,reportData.itemcount));
});
notifyListeners();
}
catch(error)
{
_errorMessage = "Server error";
notifyListeners();
}
}
else
{
_progressStatuc = false;
_chartVisible = false;
_errorVisible = true;
_errorMessage = "No Internet Connection";
notifyListeners();
}
}


}

报表.dart

class Report extends StatefulWidget
{
@override
State<StatefulWidget> createState() {
return ReportState();
}
}
class ReportState extends State<Report>
{
@override
Widget build(BuildContext context) {
final reportProvider = Provider.of<ReportProvider>(context);
reportProvider.getReportData();
//yprint(reportProvider.data.toString());
if(reportProvider.errorMessage != null &&  reportProvider.errorMessage.contains("Internet"))
{
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
title: Text("Error"),
content: Text("${reportProvider.errorMessage}"),
actions: <Widget>[
FlatButton(
child: Text("ok"),
onPressed: (){
Navigator.pop(context);
},
)
],
);
});
}
return Stack(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(8, MediaQuery.of(context).size.height*0.05,0, 0),
child: Text(
"Report",
style: TextStyle(fontSize: 28,color: Colors.black),
),
),
Row(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
margin: EdgeInsets.fromLTRB(8, 8, 0, 0),
child: GestureDetector(
onTap: (){
reportProvider.selectDate(context, "fromdate");
},
child: Text(
"${reportProvider.fromDate}",
style: TextStyle(color: Colors.black,fontSize: 16),
),
),
),
),
Expanded(
flex: 1,
child: Text(
"To",
style: TextStyle(fontSize: 16,color: Colors.grey),
),
),
Expanded(
flex: 3,
child: GestureDetector(
onTap: (){
reportProvider.selectDate(context, "todate");
},
child: Text(
"${reportProvider.toDate}",
style: TextStyle(color: Colors.black,fontSize: 16),
),
),
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: (){},
child: Icon(
Icons.check,
color: Theme.of(context).accentColor,
),
),
)
],
),
//  Visibility(
//    visible: reportProvider.chartVisible,
//     child: charts.PieChart<PieData>(
//    ),
//  ),
Expanded(
child: Visibility(
visible: reportProvider.errorVisible,
child: Container(
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset('assets/images/undraw_report.svg',width: MediaQuery.of(context).size.width,height: MediaQuery.of(context).size.height*0.40),
Text(
"No Reports are available",
style: TextStyle(color: Colors.black,fontSize: 20),
)
],
),
),
),
)
],
),
],
);
}
}

根据文档,每次发生更改时都会调用build((方法。如果希望只触发一次调用,可以使用initState((方法并添加一些helper方法来更新UI。示例如下:https://flutter.dev/docs/get-started/flutter-for/android-devs#what-相当于颤振中的runonuitread

从上一个链接异步加载的示例,特别注意loadData方法:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
List widgets = [];
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context, int position) {
return getRow(position);
},
),
);
}
Widget getRow(int i) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Text("Row ${widgets[i]["title"]}"),
);
}
Future<void> loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = json.decode(response.body);
});
}
}

最新更新