1

I have a Stack of two custom widgets, which both are Positioned:

  1. ProfileCard
  2. ProfileCardDummy

ProfileCard: This custom Stateful Widget is the widget of the first stack, the stack on the top. This widget ris Dismissible.

ProfileCardDummy: This custom Stateless widget is the background widgets of the stack.

So ProfileCard widget is the one on the top of the Stack, and the other background stacks are ProfileCardDummy

My Code is something like that:

return Stack(
    alignment: AlignmentDirectional.center,
    children:
    state.profileCards.map((ProfileCardModel card) {

        backCardWidth += 10.0;
        backBottom -= decrementalBottom;

        if (state.profileCards.indexOf(card) ==
            state.profileCards.length - 1) {
            return BlocProvider < ProfileCardBloc > (
                bloc: _profileCardBloc,
                child: ProfileCard(
                    isBack: 0,
                    bottom: initialBottom,
                    cardModel: card,
                    rotation: 0.0,
                    skew: 0.0,
                    img: image1,
                    addCard: () {},
                    onPressed: () {},
                ),
            );
        } else {
            return ProfileCardDummy(
                card,
                image2,
                backBottom,
                backCardWidth,
            );
        }
    }).toList()
);

All the magic happens in ProfileCard, where I'm fetching content of the card (mainly buttons) using BloC pattern.

I'm dispatching the bloc event on the constructor of the ProfileCard state. Something like:

class _ProfileCardState extends State<ProfileCard> {
  final VoteButtonBloc _voteButtonBloc = VoteButtonBloc();


  _ProfileCardState(){
    print("Dispatching ${widget.cardModel}");
    _voteButtonBloc.dispatch(FetchButtons(widget.cardModel));
  }
...
...

Problem is, that when I run the code, the first ProfileCard shows its buttons correctly. Now when I dismiss it, the second ProfileCard shows, but with the buttons of the first ProfileCard (the one I dismissed).

After hours of debugging, I noticed that the constructor of the ProfileCard (_ProfileCardState()) is being called only on the first card. Other cards are inheriting the buttons of the first class.

In the documentation of Stack, it says:

If you reorder the children in this way, consider giving the children non-null keys.
These keys will cause the framework to move the underlying objects for the children to their new locations rather than recreate them at their new location.

My ProfileCard takes a key as argument (as it's extending StatefulWidget), but I'm not passing any key. Passing a Key would solve this? How to pass a unique key?:P

Is there a method to force the recreation of the widget to force the constructor being called again, and thus fetching the buttons correctly?

Lambasoft
  • 909
  • 2
  • 14
  • 33

1 Answers1

2

First things first. When you have the same widgets on a list, Flutter won't know if they've changed order or not, that's where the key may help you.

To see how to use the keys you may want to check here and this video that explains quite well for list scenarios where you want to re-order an item, for example.

A setState will call the build in the widgets state present already in the tree, but won't call the constructor or initState, those are only when the widget is actually inserted in the tree. When the parent changes, Flutter will look for changes on its children and call the didUpdateWidget method on each widget state where you can override and actually compare the changes of the old widget with the new one.

Since you always want to rebuild the widget, just give it a UniqueKey as such

ProfileCard(key: UniqueKey());

That will tell Flutter that you are actually creating a new object instead of re-using the old one.

Miguel Ruivo
  • 16,035
  • 7
  • 57
  • 87
  • 1
    Thank you very much for your answer, made things very clear for me. Do you recommend using the same type of widgets on all the Stack widgets so they do not recreated? In my scenario, only difference between ProfileCardDummy and ProfileCard is that ProfileCard is Dismissable – Lambasoft Feb 04 '19 at 18:14
  • No, you are free to use whatever widget you want inside of the stack. The stack is just a layout container that positionate and/or overlap it’s children widgets. – Miguel Ruivo Feb 04 '19 at 18:31