Flutter Bloc 状态管理

Posted

技术标签:

【中文标题】Flutter Bloc 状态管理【英文标题】:Flutter Bloc state management 【发布时间】:2021-03-04 22:03:03 【问题描述】:

我正在尝试构建基于 Flutter 的平板电脑应用程序。因为平板电脑上有更多的屏幕空间,所以每个页面都由一组小部件组成,每个小部件都使用自己的 bloc 实现构建。

我对 Flutter 和 bloc 还很陌生,当前的设计只是为每个改变小部件树生成方式的状态更改重新生成小部件树。也许我不明白,更可能是真的,当状态改变发生时,bloc builder 是返回一个小部件。我还没有看到保存页面小部件并且新状态只是修改保存的小部件的示例。

这是我遇到的问题的一个示例。我正在使用一个 bloc 观察者来监视块的状态。

当前的小部件树如下所示:

LocaleTile [LocaleTileBloc, LocaleTileInit] 
    NeighborColumn [NeighborBloc, NeighborInit] 
    LocaleColumn [RegionBloc, RegionInit] 
    FamilyColumn [FamilyBloc, FamilyInit] 

NewLocaleEvent 的事件到状态映射如下所示:

Stream<LocaleTileState> _mapNewLocaleToState(NewLocaleEvent event) async* 
    yield LocaleTileLaughing();
    yield NewLocaleState(event.locale);
  

当用户按下区域设置按钮时,我会向 LocaleTileBloc -> NewLocaleEvent 发送一个事件。观察者日志是:

// Create NewLocaleEvent
: onEvent -- b: LocaleTileBloc, e: NewLocaleEvent: Bellevue

// Consume the NewLocaleEvent
: onTrans -- b: LocaleTileBloc, t: Transition  currentState: LocaleTileInit, 
                                                event: NewLocaleEvent: Bellevue, 
                                                nextState: NewLocalState: Bellevue 
: onChange -- c: LocaleTileBloc, c: Change  currentState: LocaleTileInit, 
                                             nextState: NewLocalState: Bellevue 
// The widget that implements the LocalTileBloc receives the new state
: RegionLocalTile[LocaleTileBloc] State: NewLocalState: Bellevue

如果用户按下新的区域设置来显示它,我会在观察者日志中得到以下信息:

// Create NewLocaleEvent Kirkland
: onEvent -- b: LocaleTileBloc, e: NewLocaleEvent: Kirkland

// Consume NewLocalState
// Where did this come from
: RegionLocalTile[LocaleTileBloc] State: NewLocalState: Bellevue

当重新生成页面小部件时,似乎 bloc 告诉新的 RegionLocalTile 小部件它必须回到旧状态,因此应用程序执行所有 api 调用以重新生成页面,然后:

: onTrans -- b: LocaleTileBloc, t: Transition  currentState: NewLocalState: Bellevue, 
                                                event: NewLocaleEvent: Kirkland, 
                                                nextState: LocaleTileLaughing 
: onChange -- c: LocaleTileBloc, c: Change  currentState: NewLocalState: Bellevue, 
                                             nextState: LocaleTileLaughing 

: onTrans -- b: LocaleTileBloc, t: Transition  currentState: LocaleTileLaughing, 
                                                event: NewLocaleEvent: Kirkland, 
                                                nextState: NewLocalState: Kirkland 
: onChange -- c: LocaleTileBloc, c: Change  currentState: LocaleTileLaughing, 
                                             nextState: NewLocalState: Kirkland 
: RegionLocalTile[LocaleTileBloc] State: NewLocalState: Kirkland

然后小部件页面会获得正确的状态。

我想我的问题是:当实现一个块的小部件响应状态变化时,它必须返回一个小部件。有两种选择,要么重新生成小部件,要么将其保存在有状态的小部件中并创建键来修改特定的子小部件。

如果我在每次状态更改时重新生成它,那么每次小部件出现时,它都会被提醒它的旧状态,并且必须重做它刚刚离开的所有工作。我希望我可以重置集团以回到初始状态。

【问题讨论】:

【参考方案1】:

我决定如何解决这个问题是保存通过的小部件,那些不会根据状态变化改变用户界面的小部件,然后将它们重新插入到小部件树中。确实更改 ui 的小部件会生成新的小部件,并将新部件插入树中。此更改保存了多个重复的 api 调用,因为块不必告诉小部件将其状态重置为上一个状态,然后转到新状态:

通常父母的状态如下:

class _RegionState extends State<RegionPage> 

    LocaleTile localeTile;

    @override
    void initState() 
      super.initState();
      localeTile = null;
    

    Widget getWidget(BlocState state) 
      if (localeTile == null) 
        localeTile = new LocaleTile(state);
      
      return Center( child: localeTile);
    

    @override
    Widget build(BuildContext context) 
      return BlocBuilder<EntityBloc, EntityState>(builder: (context, state) 
          if (state is EntityLoaded) 
            ...
            // computeSomething();
            // Send events to the localTileBloc
          
          return getWidget(state);
      );
    

    

【讨论】:

以上是关于Flutter Bloc 状态管理的主要内容,如果未能解决你的问题,请参考以下文章

Flutter BLoC:管理主要数据类型的状态

Flutter 状态管理之Bloc上

Flutter 状态管理之Bloc上

Flutter 状态管理之Bloc上

Flutter Bloc 状态管理

Flutter 状态管理BLoC