0

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

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

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

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

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

I send an event to the LocaleTileBloc -> NewLocaleEvent when the user presses on a locale button. The observer log is:

// 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}

If the user presses on a new Locale to show it, I get the following in the observer log:

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

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

When the page widget is regenerated, it seems that the bloc tells the new RegionLocalTile widget that it has to go back to the old state, so the application does all of the api calls to regenerate the page, then:

: 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}

The widget page then gets the correct state.

I think my question is: When the widget that implements a bloc responds to a state change, it has to return a widget. There are two choices, either regenerate the widget or save it in a statefull widget and create keys to modify specific sub widgets.

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

4

1 回答 1

0

我决定如何解决这个问题是保存通过的小部件,那些不会根据状态变化改变 ui 的小部件,然后将它们重新插入到小部件树中。改变 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);
      });
    }

    
于 2020-11-23T00:23:29.243 回答