如何在 Navigator.Pop 或 Push 中刷新状态

Posted

技术标签:

【中文标题】如何在 Navigator.Pop 或 Push 中刷新状态【英文标题】:how to refresh state on Navigator.Pop or Push in flutter 【发布时间】:2020-02-11 18:13:04 【问题描述】:

这里我有两个页面,第一个页面叫做BSP_signup_terms,第二个页面叫做Bsp_Service_page。当我在该页面上的BSP_signup_terms 上时,我必须根据所选复选框选择一些复选框,它会向我显示一些数据。但问题是它会向我显示完整的数据,但是当我从Bsp_signup_page 回到BSP_signup_terms 并且我正在更改复选框,然后当我再次按下下一步按钮时,它不会改变结果它与以前的结果。

这是输出页面的图像

在这张图片中,当我只选择一个复选框时,我已经附加了两个屏幕输出,它会在服务页面中呈现一些值,当我回到条款和条件页面并再选择一个复选框时,它将不更新服务页​​面

这是我尝试过的代码。


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);
              ,
            );
          ),
        );
      ,
    );
  

【问题讨论】:

可以帮忙 - ***.com/questions/49804891/… 可以分享BspServiceScreen的代码吗?这就是问题所在。 问题已更新。请检查一下 打印(model.toJson());在进入服务页面之前打印正确的值但是当你到达服务页面时它显示另一个值? 是的,它正在打印正确的值,但是当我尝试显示它时。它只会输出一次 【参考方案1】:

返回第一页后可以使用setState():

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

【讨论】:

你能稍微解释一下,我要在哪里使用吗?? 不,它不起作用你有其他解决方案吗? 请尝试使用 Navigator.pop() 而不是 NavigationHelper.navigatetoBack(context); 我误会了,您想在弹出第二页后刷新第一页,但您想要的是刷新第二页。当您推送到新页面时,该页面将重建状态,因此您的原因不是导航器而是您的代码 我真的很想要,但我不知道你在复选框中做了什么,以及为了使第二页发生变化而发生的变化。只需先尝试一些简单的测试即可【参考方案2】:

请尝试以下代码:-

首先你添加一个方法异步方法:-

void redirectToNextScreen() async 
    final Route route = MaterialPageRoute(
        builder: (context) => BspServicePage(bspSignupCommonModel: model));
    final result = await Navigator.push(mContext, route);
    try 
      if (result != null) 
        if (result) 
          //Return callback here.
        
      
     catch (e) 
      print(e.toString());
    
  

然后接下来你可以在Next按钮按下事件的“BSP_Signup_Terms_Page”中调用这个方法。

其次,您可以在“BspServicePage”屏幕NextCancel事件中添加以下行。

Navigator.pop(mContext, true); //true means refresh back page and false means not refresh.

【讨论】:

不,伙计,它不起作用。我的服务页面块仍然没有刷新。当我重新启动时,它只是刷新

以上是关于如何在 Navigator.Pop 或 Push 中刷新状态的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 navigator.pop 刷新或重新加载页面...比如第 1(nav.push=>2)页面到第 2 页,然后从第 2(nav.pop,值)返回到第 1 页?

如何在 Flutter 中的 navigator.pop(context) 之后显示小吃栏?

Flutter 图像在 navigator pop 上再次下载

使用 page_transition 更改 Navigator.pop() 动画持续时间

Navigator.pop() - 如何传递 `context` 以供导航器读取 -

运行 navigator.pop() 后如何刷新 React 状态?