简体   繁体   中英

Flutter: (How) Can I have a PageView of widgets that each rely on Provider?

I'm trying to design my app with Providers and MobX "Stores" , and can't figure out a proper way to use Providers/Stores within widgets that may be included in a PageView.

I have a StatelessWidget "PlayerPage" which displays data from a single observable "Player" object from a "PlayerStore" which is provided inside the PlayerPage with Provider.of.

In some parts of my app, one PlayerPage is all there is, but in other parts, several PlayerPages are contained in a PageView supplied with a list of Players (from a "TeamStore").

Since the PageView builds a few PlayerPages at a time and I have the one PlayerStore containing a single Player at a time, this didn't work.

I figured out a semi-workaround with setting PlayerStore's Player in PageView's "onPageChanged" rather than the "itemBuilder", but then I get MobX messages about how “There are no observables detected in the builder function for Observer@(number)” (I assume from the built PlayerPages not shown) along with some other problems when jumping to a page, and I'm thinking there must be a better way to handle all of this…

Can someone please tell me where I've gone wrong (whether with PageViews or a deeper misunderstanding of Provider/MobX)?

class PlayerPage extends StatelessWidget {

  const PlayerPage({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {

    PlayerStore playerStore = Provider.of<PlayerStore>(context);

    return Column(
      children: <Widget>[
        Observer(
          builder: (_) =>
              SinglePlayerStatsDisplay(
                playerStore: playerStore,
              ),
        ),
        Observer(
          builder: (_) =>
              PlayerStatControls(
                playerStore: playerStore,
              ),
        ),
      ],
    );
  }
}

...

class PlayersPageViewState extends State<PlayersPageView> {

  @override
  void initState() {
    super.initState();

    _pageController = PageController(initialPage: widget.startingIndex);
    widget.playerStore
    .setPlayer(widget.teamStore.players[widget.startingIndex]);
  }

  ...

    body: PageView.builder(
            itemBuilder: (BuildContext context, int index) => PlayerPage(),
            itemCount: widget.teamStore.players.length,
            onPageChanged: (index) => widget.playerStore.setPlayer(widget.teamStore.players[index]),
            controller: _pageController,
          )

    ...
}

...

abstract class _PlayerStore implements Store {
  @observable
  Player player;

  @action
  setPlayer(Player newPlayer) => player = newPlayer;

  ...
}

The problem is that you are using Observer , but doesn't observe anything.

Observer(
  builder: (_) =>
      SinglePlayerStatsDisplay(
        playerStore: playerStore,
      ),
),

While playerStore is observable, you are passing it as is . In that case, Observer is not needed at all and can be removed.

Observer would only be needed for something like:

Observer(
  builder: (_) => Text(playerStore.foo.toString()),
),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM