【问题标题】:How to Rebuild or Refresh a Statefull Class from an other Statefull Class in Flutter?如何从 Flutter 中的另一个有状态类重建或刷新一个有状态类?
【发布时间】:2021-02-06 16:19:47
【问题描述】:

是否可以从另一个类重建或刷新一个类?

例如,我有一个名为“HomeScreen”的类和一个名为“SubScreen”的类。我可以通过底部导航栏在这和类之间导航。

现在我在 SubScreen 类中进行了一些更改。但是当我通过底部导航栏导航回“HomeScreen”时,旧值仍在“HomeScreen”内。当我关闭并重新打开我的应用程序时,“HomeScreen”中的所有内容都会更新。如何在不关闭应用程序的情况下实现“更新”?

请帮我解决这个问题,我卡在那里差不多好几个星期了...

【问题讨论】:

    标签: flutter class widget rebuild


    【解决方案1】:

    当您导航回该页面时,使用导航器上的 then 刷新主屏幕。我希望它能帮助你实现你的要求

    而且我还需要知道您在应用程序中使用 Provider。这意味着它更容易。

    Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => SubScreen()),
      ).then((_){
       setState((){});
    });
    

    【讨论】:

    • 也谢谢@Balasubramani Sundaram!我的问题是,我使用的是底部导航栏,并且 Navigator.push 无法访问这些页面。但我也会在其他代码中尝试您的示例!
    【解决方案2】:

    仅使用 Statefull 小部件:

    • 您可以将回调传递给第二个屏幕,并在第一个屏幕上的状态也应该更新时调用它。这种方法的缺点是它会更新整个小部件。

    子屏幕

      class SubScreen extends StatefulWidget {
      final Function updateCallback;
      SubScreen({@required this.updateCallback});
    
      // rest of your State class  
      
      // in the State class, when you want to refresh the HomeScreen, call:
       widget.updateCallback(); // or a more safe option: widget.updateCallback?.call();
      }
    
    
    class _HomeScreenState ...{
      
      //where you push the second screen
      ...
      Navigator.push(context, SubScreen(updateCallback: (){
       setState((){});
      })
      ...
    }
    

    更有效的方法: 您可以阅读有关 state management approaches here 的更多信息
    rxDart 示例:
    为简单起见,我在主屏幕中创建主题并将主题传递给子屏幕。

    子屏幕

      class SubScreen extends StatefulWidget {
      final BehaviourSubject<SomeModel> stateSubject;
      SubScreen({@required this.stateSubject});
    
      // rest of your State class  
       
      // in the State class, when you want to refresh the HomeScreen, call:
       widget.stateSubject.add(newItems); //newItems is the state that you want to present on the HomeScreen too.
      // where you want to use this SomeModel state, wrap your Widget with StreamBuilder<SomeModel>, pass the widget.stateSubject as the stream, and in the builder function you can listen to changes. Example in the build just below
    
     Widget build(BuildContext context){
        StreamBuilder<SomeModel>(
            stream: widget.stateSubject,
            initialData: null, //null be default, but you can set like empty array, or anything you want
            builder: (context, snapshot) {
              var state = snapshot.data;
               // here the state contains the latest value of the subject because its a BehaviourSubject, and you will get every new state that is added to this subject.
             return Container;
            });
     }
    }
    
    

    主屏幕

    class _HomeScreenState ...{
        final BehaviourSubject<SomeModel> stateSubject = BehaviourSubject.seeded(null); //null by default, but you can set an initial value if you need
    
      //where you push the second screen
      ...
      Navigator.push(context, SubScreen(stateSubject: stateSubject));
      ...
    
      Widget build(context){
        //here you need to wrap your widget where you want to update based on the subject
       }
    }
    

    【讨论】:

    • 谢谢@Dániel Rózsa!我会仔细阅读所有内容并在我的项目中尝试一下!
    • 嘿@Dániel Rózsa! :) 我有个问题。我已经试过了,你发给我的,但我仍然无法实现我的目标。我的问题是,我使用的是底部导航栏,所以我不能使用 Push Navigator 中的方法。这对我来说很烦人,因为没有什么对我有用。我也不能在这里上传我的代码,因为它太长了……太可怕了:(
    • 也许这会有所帮助。在子类中,我有一个 GridView.builder。当我通过底部导航栏导航到此类时,屏幕总是最新的。在 HomeScreen 内,我有一个 .map,它显示了一些内容。但是当我通过底部导航栏导航时,主屏幕内没有任何变化。只有当我重新启动我的应用程序时。我已经读到 .map 可能会导致这个问题,为什么它不重建小部件,但我需要这个 .map 并且我无法找到适合我的解决方案。
    • 您可以尝试创建一个类(例如 LocationProvider),使其成为单例并在其中添加 BehaviorSubject,然后从两个屏幕访问和更新该主题。您应该使用 StreamBuilder 包装您的地图。地图肯定会重建绘图元素(标记、线条、圆圈等)。
    • 好吧,这听起来合乎逻辑。谢谢你,我会试试的! :)
    猜你喜欢
    • 1970-01-01
    • 2020-08-14
    • 2019-02-14
    • 2019-10-06
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2018-12-04
    • 2023-03-23
    相关资源
    最近更新 更多