从另一个小部件更改一个小部件中的状态

Posted

技术标签:

【中文标题】从另一个小部件更改一个小部件中的状态【英文标题】:Change state in one Widget from another widget 【发布时间】:2019-12-17 06:26:01 【问题描述】:

我正在编写一个 Flutter 应用程序,其中向用户展示了一个 PageView 小部件,该小部件允许他/她通过滑动在 3 个“页面”之间导航。

我遵循https://medium.com/flutter-community/flutter-app-architecture-101-vanilla-scoped-model-bloc-7eff7b2baf7e 中使用的设置,我使用单个类将数据加载到我的模型中,这应该反映相应的状态变化 (IsLoadingData/HasData)。

我有一个包含所有 ViewPage 小部件的主页。页面是在 MainPageState 对象中构造的,如下所示:

  @override
  void initState() 
    _setBloc = SetBloc(widget._repository);
    _notificationBloc = NotificationBloc(widget._repository);
    leftWidget = NotificationPage(_notificationBloc);
    middleWidget = SetPage(_setBloc);
    currentPage = middleWidget;
    super.initState();
   

如果我们进入 NotificationPage,那么它做的第一件事就是尝试加载数据:

      NotificationPage(this._notificationBloc) 
        _notificationBloc.loadNotificationData();
      

which should be reflected in the build function when a user directs the application to it:

  //TODO: Consider if state management is correct
  @override
  Widget build(BuildContext context) 
    return StreamBuilder<NotificationState>(
      stream: _notificationBloc.notification.asBroadcastStream(),
      //initialData might be problematic
      initialData: NotificationLoadingState(),
      builder: (context, snapshot) 
        if (snapshot.data is NotificationLoadingState) 
          return _buildLoading();
        
        if (snapshot.data is NotificationDataState) 
          NotificationDataState state = snapshot.data;
          return buildBody(context, state.notification);
         else 
          return Container();
        
      ,
    );
  

发生的情况是,即使在存储库中加载了数据,屏幕也会始终点击“NotificationLoadingState”:

  void loadNotificationData() 
    _setStreamController.sink.add(NotificationState._notificationLoading());
    _repository.getNotificationTime().then((notification) 
      _setStreamController.sink
          .add(NotificationState._notificationData(notification));
      print(notification);
    );
  

通知是在另一个不是通知页面的页面上打印的。

我做错了什么?

【问题讨论】:

【参考方案1】:
//....

class _SomeState extends State<SomeWidget> 

 //....
 Stream<int> notificationStream;
 //....

 @override
  void initState() 
   //....
    notificationStream = _notificationBloc.notification.asBroadcastStream()
    super.initState();
   

    //....
   Widget build(BuildContext context) 
    return StreamBuilder<NotificationState>(
      stream: notificationStream,
     //....    

将您的 Stream 保存在某处并停止每次初始化它。 我怀疑 build 方法被多次调用,因此您创建了一个新流(initState 被调用一次)。

如果这有帮助,请尝试告诉我。

【讨论】:

我正在调查这些问题,因为我认为您在创建多个流这一事实上是正确的,但我似乎无法让它正常工作。例如,如果我在主页中检查通知页面的状态,则主页会回答有数据。然而,通知页面将继续加载,就好像它没有数据一样。

以上是关于从另一个小部件更改一个小部件中的状态的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个小部件设置状态?

从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter

如何在另一个小部件中管理小部件状态

如何从另一个小部件类更新小部件树 - Flutter

如何从另一个小部件状态处理一个小部件状态?

当 Flutter 中的全局变量更改(异步)时更新小部件