Reputation: 476
I am building this card game app which has a list of Cards (containers with special effects) and the list is managed and updated by the Provider/Consumer mechanism.
class LowerSectionWithScrollingCardList extends StatefulWidget {
@override
_LowerSectionWithScrollingCardListState createState() =>
_LowerSectionWithScrollingCardListState();
}
class _LowerSectionWithScrollingCardListState
extends State<LowerSectionWithScrollingCardList> {
@override
Widget build(BuildContext context) {
return Consumer<GameState>(builder: (context, gameState, child) {
print('lower list ${gameState.gcurrentPlayers[0].ownList}');
return Expanded(
flex: 34,
child: Container(
color: Colors.white,
child: ListView(
children: gameState.gcurrentPlayers[0].ownList,
scrollDirection: Axis.horizontal,
),
),
);
});
}
}
gameState.gcurrentPlayers[0].ownList is the first player which is us, and ownlist is the actual list of widgets or cards which gets updated by clicking some other buttons in the app.
the list is updated by this method exactly
void ggiveCardToCurrentPlayer(int howMuch){
for(int i=0;i<howMuch;i++)
ggetPlayerWithCurrentTurn().ownList.add(gplayingCards.removeLast());
notifyListeners();
}
Now after the "notifylisteners" is called, I am 100% sure that the Consumer is updated with the new data, because the print statement in the build method prints the newly added cards.
Finally, the issue is that the listView itself doesn't update while the list it renders has those added cards.
I checked out a few posts regarding a similar issue and they suggest that one add keys to the Data items, in my case the data items are my cards, and I added keys to them. No change.
class RegularUnoCard extends StatelessWidget{
final Color _color;
final String _value;
final Key _key;
RegularUnoCard(this._color, this._value,this._key);
@override
Widget build(BuildContext context) {
return Container(
key: _key,
margin: EdgeInsets.symmetric(
vertical: _cardMarginVer, horizontal: _cardMarginHor),
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(_cardCornerRadii),
border: Border.all(color: _color, width: 4, style: BorderStyle.solid),
boxShadow: [
BoxShadow(
color: _color,
spreadRadius: (_value == plus2) ? 8 : 2,
blurRadius: 5)
],
color: Colors.white,
),
child: Container(
height: _cardHeight,
width: _cardWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(60),
color: _color,
),
child: Center(
child: getLogo(),
),
),
);
}
I hope this the correct way of putting keys in the Cards.
I also read that one must call setState() but I dont have any place to call Setstate from within my listView.
I have tried replacing the ownList logic with Provider.of(context).playerlist[0].ownlist etc etc but that too doesnt work
I hope I have supplied enough data for this evaluation. Please comment if more information is required. Thanks a lot for your time and suggestions.
Upvotes: 1
Views: 1579
Reputation: 476
I read more about the problem, the source which was helpful was this
Basically my list was being updated but I was providing the reference of the array, and since flutter works on immutable data, it did not detect my array change. So all I had to do was to build a new list from the existing reference array.
children: List<Widget>.from(gameState.gcurrentPlayers[0].ownList),
The final ListView should look like
@override
Widget build(BuildContext context) {
return Consumer<GameState>(builder: (context, gameState, child) {
print('lower list ${gameState.gcurrentPlayers[0].ownList}');
return Expanded(
flex: 34,
child: Container(
color: Colors.white,
child:ListView(
children: List<Widget>.from(gameState.gcurrentPlayers[0].ownList),
scrollDirection: Axis.horizontal,
),
),
);
},key: UniqueKey(),);
}
}
Now my card game is updating with the new cards!!
Upvotes: 1