how to refresh state on Navigator.Pop or Push in flutter

Rutvik Gumasana picture Rutvik Gumasana · Oct 15, 2019 · Viewed 11.9k times · Source

Here I have two pages first is called BSP_signup_terms page and the second is Bsp_Service_page. when I am on BSP_signup_terms on that page I have to select some checkbox based on the selected checkbox it will show me some data. but problem is that it will show me the complete data but when I get back to the BSP_signup_terms from Bsp_signup_page and I am changing the checkbox and then again when I am pressing next button it will not change the result it same as the previous result.

Here is the Image of Output Page

In this image I've attached both screen output when I am selecting only one checkbox it will render some value in service page and when I am back to the Terms and Condition page and select one more checkbox then it will not updating service page

Here is the code I've tried.


BSP_Signup_Terms_Page

class BspLicensedSignupTermsPage extends StatefulWidget {
  static const String routeName = "/bspLicensedSignupTerms";
  final BspSignupCommonModel bspSignupCommonModel;

  BspLicensedSignupTermsPage({
    Key key,
    @required this.bspSignupCommonModel,
  }) : super(key: key);

  @override
  _BspLicensedSignupTermsPageState createState() =>
      _BspLicensedSignupTermsPageState();
}

class _BspLicensedSignupTermsPageState
    extends State<BspLicensedSignupTermsPage> {
  @override
  void initState() {
    super.initState();
  }

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  bool _isWalkIn = false;
  bool _isHome = false;
  bool _isOnDemand = false;



  Widget _buildselectcheckbox() {
    return Text(
      AppConstantsValue.appConst['bsplicensedsignupterms']['selectcheck']
          ['translation'],
    );
  }

  // Walkin
  _onCustomerWalkin(value) {
    setState(() {
      _isWalkIn = value;
    });
  }

  Widget _buildCustomerWalkIn() {
    return TudoConditionWidget(
      text: AppConstantsValue.appConst['bsplicensedsignupterms']
          ['CustomerWalkIn']['translation'],
      onChanged: (value) {
        print(value);
        _onCustomerWalkin(value);
      },
      validate: false,
    );
  }


  // Home
  _onCustomerInHome(value) {
    setState(() {
      _isHome = value;
    });
  }

  Widget _buildCustomerInHome() {
    return TudoConditionWidget(
      text: AppConstantsValue.appConst['bsplicensedsignupterms']
          ['CustomerInHome']['translation'],
      onChanged: (value) {
        _onCustomerInHome(value);
      },
      validate: false,
    );
  }

  Widget _buildCustomerInHomeHelp() {
    return Text(
      AppConstantsValue.appConst['bsplicensedsignupterms']['businesscheckhelp']
          ['translation'],
    );
  }

  // On Demand

  _onCustomerOnDemand(value) {
    setState(() {
      _isOnDemand = value;
    });
  }

  Widget _buildBusinessOnDemand() {
    return TudoConditionWidget(
      text: AppConstantsValue.appConst['bsplicensedsignupterms']
          ['BusinessOnDemand']['translation'],
      onChanged: (value) {
        _onCustomerOnDemand(value);
      },
      validate: false,
    );
  }

  Widget _buildBusinessOnDemandHelp() {
    return Text(AppConstantsValue.appConst['bsplicensedsignupterms']
        ['businessprovidehelp']['translation']);
  }

  @override
  Widget build(BuildContext context) {
    final appBar = AppBar(
      title: Text("Bsp Licensed Signup Terms and Condition"),
      leading: IconButton(
        icon: Icon(Icons.arrow_back_ios),
        onPressed: () {
          NavigationHelper.navigatetoBack(context);
        },
      ),
      centerTitle: true,
    );

    final bottomNavigationBar = Container(
      height: 56,
      //margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new FlatButton.icon(
            icon: Icon(Icons.close),
            label: Text('Clear'),
            color: Colors.redAccent,
            textColor: Colors.black,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {
              _formKey.currentState.reset();
            },
          ),
          new FlatButton.icon(
            icon: Icon(FontAwesomeIcons.arrowCircleRight),
            label: Text('Next'),
            color: colorStyles["primary"],
            textColor: Colors.white,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {
              if (_formKey.currentState.validate()) {
                if (_isHome == false &&
                    _isOnDemand == false &&
                    _isWalkIn == false) {
                  showDialog(
                      barrierDismissible: false,
                      context: context,
                      builder: (context) => ShowErrorDialog(
                            title: Text('Select Service'),
                            content: Text(
                              'Please select atleast one service type to proceed next',
                            ),
                          ));
                } else {
                  BspSignupCommonModel model = widget.bspSignupCommonModel;
                  model.isWalkin = _isWalkIn;
                  model.isHome = _isHome;
                  model.isOnDemand = _isOnDemand;
                  print(model.toJson());
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) =>
                          BspServicePage(bspSignupCommonModel: model),
                    ),
                  );
                }
              }
            },
          ),
        ],
      ),
    );
    return new Scaffold(
      appBar: appBar,
      bottomNavigationBar: bottomNavigationBar,
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Stack(
          children: <Widget>[

            SingleChildScrollView(
              child: SafeArea(

                child: Form(
                  autovalidate: true,
                  key: _formKey,
                  child: Scrollbar(
                    child: SingleChildScrollView(
                      dragStartBehavior: DragStartBehavior.down,
                      padding: const EdgeInsets.symmetric(horizontal: 10.0),
                      child: new Container(
                        decoration: BoxDecoration(
                            borderRadius: new BorderRadius.circular(25)),
                        child: new Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            _buildselectcheckbox(),
                            _buildCustomerWalkIn(),
                            _buildCustomerInHome(),
                            _buildCustomerInHomeHelp(),
                            _buildBusinessOnDemand(),
                            _buildBusinessOnDemandHelp(),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

BSP_Service_Page

class BspServicePage extends StatefulWidget {
  static const String routeName = "/bspService";
  final BspSignupCommonModel bspSignupCommonModel;

  BspServicePage({
    Key key,
    @required this.bspSignupCommonModel,
  }) : super(key: key);

  @override
  _BspServicePageState createState() => _BspServicePageState();
}

class _BspServicePageState extends State<BspServicePage> {
  List<int> servicesIds = [];
  Map<String, bool> selection = {};
  List<BspServices.Service> selectedServices = [];
  SearchBarController _controller = new SearchBarController();
  String _searchText = '';
  bool refreshservices = true;

  @override
  void initState() {
    super.initState();
  }

  void _showErrorDialog(String message) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (context) => ShowErrorDialog(
        title: Text('An Error Occurred!'),
        content: Text(message),
      ),
    );
  }

  void refresh() {
    setState(() {
      refreshservices = !refreshservices;
    });
  }

  @override
  Widget build(BuildContext context) {
    var _bspServiceBloc = new BspServiceBloc();
    final appBar = SearchBar(
      controller: _controller,
      onQueryChanged: (String query) {
        print('Search Query $query');
        setState(() {
          _searchText = query;
        });
      },
      defaultBar: AppBar(
        centerTitle: true,
        leading: IconButton(
            icon: Icon(Icons.arrow_back_ios),
            onPressed: () {
              refresh();
              NavigationHelper.navigatetoBack(context);
            }),
        title: Text('Select Services'),
      ),
    );

    final bottomNavigationBar = Container(
      height: 56,
      // margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new FlatButton.icon(
            icon: Icon(Icons.close),
            label: Text('Clear'),
            color: Colors.redAccent,
            textColor: Colors.black,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {
              print('reseting the state');
              setState(() {
                selection = {};
                servicesIds = [];
              });
            },
          ),
          new FlatButton.icon(
            icon: Icon(FontAwesomeIcons.arrowCircleRight),
            label: Text('Next'),
            color: colorStyles["primary"],
            textColor: Colors.white,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {
              BspSignupCommonModel model = widget.bspSignupCommonModel;
              model.servicesIds = servicesIds;
              model.services = selectedServices;
              print('servicesIds at the next button');
              print(servicesIds);
              print(model.toJson());
              if (servicesIds.length == 0) {
                _showErrorDialog(
                    'You need to select at least one service to proceed next!');
              } else {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => BusinessProfilePage(
                      bspSignupCommonModel: model,
                    ),
                  ),
                );
              }
            },
          ),
        ],
      ),
    );
    return new Scaffold(
      appBar: appBar,
      bottomNavigationBar: bottomNavigationBar,
      body: new BspServiceScreen(
        bspServiceBloc: _bspServiceBloc,
        bspSignupCommonModel: widget.bspSignupCommonModel,
        servicesIds: servicesIds,
        selection: selection,
        searchQuery: _searchText,
        selectedServices: selectedServices,
        refresh: refresh,
      ),
    );
  }
}

Bsp_service_screen

class BspServiceScreen extends StatefulWidget {
  final BspServiceBloc _bspServiceBloc;
  final String searchQuery;
  final List<int> servicesIds;
  final Map<String, bool> selection;
  final BspSignupCommonModel bspSignupCommonModel;
  final List<BspServices.Service> selectedServices;
  final Function refresh;

  const BspServiceScreen({
    Key key,
    @required BspServiceBloc bspServiceBloc,
    @required this.bspSignupCommonModel,
    @required this.servicesIds,
    @required this.selection,
    @required this.selectedServices,
    @required this.refresh,
    this.searchQuery,
  })  : _bspServiceBloc = bspServiceBloc,
        super(key: key);

  @override
  BspServiceScreenState createState() {
    return new BspServiceScreenState(_bspServiceBloc);
  }
}

class BspServiceScreenState extends State<BspServiceScreen> {
  final BspServiceBloc _bspServiceBloc;

  BspServiceScreenState(this._bspServiceBloc);
  // Map<String, bool> _selection = {};

  @override
  void initState() {
    super.initState();
    bool isHome = widget.bspSignupCommonModel.isHome;
    bool isWalkIn = widget.bspSignupCommonModel.isWalkin;
    bool isOnDemand = widget.bspSignupCommonModel.isOnDemand;
    this._bspServiceBloc.dispatch(LoadBspServiceEvent(
          countryId: 1,
          isHome: isHome,
          isOnDemand: isOnDemand,
          isWalkin: isWalkIn,
        ));
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<BspServiceBloc, BspServiceState>(
      bloc: widget._bspServiceBloc,
      builder: (
        BuildContext context,
        BspServiceState currentState,
      ) {
        if (currentState is UnBspServiceState) {
          return Center(child: CircularProgressIndicator());
        }
        if (currentState is ErrorBspServiceState) {
          return new Container(
            child: new Center(
              child: new Text(currentState.errorMessage ?? 'Error'),
            ),
          );
        }
        if (currentState is InBspServiceState) {
          // print(
          //     'in bsp service state, ${currentState.bspServices.servicesByCountry.length}');
          if (currentState.bspServices.servicesByCountry.length == 0) {
            return Container(
              child: Center(
                child: Text("No Services available for this combination"),
              ),
            );
          } else {
            return new Container(
              child:
                  _renderServices(currentState.bspServices.servicesByCountry),
            );
          }
        }
        return Container();
      },
    );
  }

  List<ServicesByCountry> finalList = new List();

  ListView _renderServices(List<ServicesByCountry> lovCountryServices) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (widget.searchQuery != '') {
        finalList.clear();
        lovCountryServices.forEach((ServicesByCountry data) {
          if (data.name
              .toLowerCase()
              .contains(widget.searchQuery.toLowerCase())) {
            setState(() {
              finalList.add(data);
            });
          } else {
            data.services.forEach((ServiceList.Service services) {
              if (services.name
                  .toLowerCase()
                  .contains(widget.searchQuery.toLowerCase())) {
                setState(() {
                  finalList.add(data);
                });
              }
            });
          }
        });
      } else {
        setState(() {
          finalList.clear();
          finalList.addAll(lovCountryServices);
        });
      }
    });
    return ListView.builder(
      shrinkWrap: true,
      padding: const EdgeInsets.all(8.0),
      itemCount: finalList.length,
      itemBuilder: (BuildContext context, int index) {
        ServicesByCountry item = finalList[index];
        List itemsList = item.services;
        return ExpansionTile(
          title: Text(item.name),
          children: List.generate(itemsList.length, (i) {
            widget.selection[itemsList[i].name] =
                widget.selection[itemsList[i].name] ?? itemsList[i].isSelected;
            return CheckboxListTile(
              title: Text(itemsList[i].name),
              value: widget.selection[itemsList[i].name],
              onChanged: (val) {
                setState(() {
                  widget.selection[itemsList[i].name] = val;
                  if (val) {
                    widget.servicesIds.add(itemsList[i].id);

                    List<BspServices.Service> services =
                        widget.selectedServices.where((service) {
                      return service.mainCategory == item.name;
                    }).toList();

                    SubCategory subService = new SubCategory(
                      id: itemsList[i].id,
                      name: itemsList[i].name,
                    );

                    List<SubCategory> subCategories = [];
                    if (services.length == 0) {
                      subCategories.add(subService);
                      widget.selectedServices.add(
                        new BspServices.Service(
                          mainCategory: item.name,
                          mainCategoryId: item.id,
                          subCategory: subCategories,
                        ),
                      );
                    } else {
                      print('services in else');
                      print(services[0].subCategory);
                      subCategories = services[0].subCategory;
                      subCategories.add(subService);
                    }
                  } else {
                    widget.servicesIds.removeWhere((service) {
                      return service == itemsList[i].id;
                    });

                    List<BspServices.Service> services =
                        widget.selectedServices.where((service) {
                      return service.mainCategory == item.name;
                    }).toList();

                    services[0].subCategory.removeWhere((subService) {
                      return subService.id == itemsList[i].id;
                    });
                  }
                });
                print('widget.servicesIds after set state');
                print(widget.servicesIds);
              },
            );
          }),
        );
      },
    );
  }
}

Answer

hoangquyy picture hoangquyy · Oct 15, 2019

You can use setState() after return to the first page:

Navigator.push(context, MaterialPageRoute(builder: (context) => Page2())).then((value) {
  setState(() {
    // refresh state
  });
});