如何在flutter的build方法中调用provider中的方法?
Posted
技术标签:
【中文标题】如何在flutter的build方法中调用provider中的方法?【英文标题】:how to call the method in provider inside the build method in flutter? 【发布时间】:2020-08-11 07:07:45 【问题描述】:我在类中有一个方法,它扩展了从 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),
)
],
),
),
),
)
],
),
],
);
【问题讨论】:
更改为final reportProvider = Provider.of<ReportProvider>(context, listen: false);
可能会为您解决问题。
【参考方案1】:
根据documentation,每次发生变化时都会调用 build() 方法。如果您希望只触发一次调用,您可以使用initState() 方法并添加一些帮助方法来更新 UI。一个例子可以在这里找到:https://flutter.dev/docs/get-started/flutter-for/android-devs#what-is-the-equivalent-of-runonuithread-in-flutter
上一个链接的异步加载示例,特别注意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);
);
【讨论】:
在您的示例中,您没有使用提供者以上是关于如何在flutter的build方法中调用provider中的方法?的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 中,当子组件的 build 方法中没有回调时,如何从子组件中读取数据?
mvn 编译报错mavn sun.security.validator.ValidatorException: PKIX path building failed: sun.security.prov