Как вызвать метод в провайдере внутри метода сборки в флаттер? - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть метод в классе, который расширяет changeNotifier, который получает данные из API. теперь я хочу вызывать этот метод всякий раз, когда страница открывается в методе сборки, но когда я вызываю этот метод, он вызывается повторно из-за метода 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();
    }
  }




}

Report.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),
                                    )
                   ],
                 ),
               ),
             ),
           )

         ],
       ),

     ],
   );
  }

}

1 Ответ

0 голосов
/ 27 апреля 2020

Согласно документации , метод build () будет вызываться каждый раз, когда что-то меняется. Если вы хотите, чтобы вызовы запускались только один раз, вы можете использовать метод initState () и добавить несколько вспомогательных методов для обновления пользовательского интерфейса. Пример можно найти здесь: https://flutter.dev/docs/get-started/flutter-for/android-devs#what -is-эквивалент-runonuithread-in-flutter

Пример асинхронной загрузки c по предыдущей ссылке, особое внимание 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);
    });
  }
}

...