I have a provider that is listening for changes to a playerList
class:
import 'package:flutter/material.dart';
import 'package:scam_artist/constants/PlayerColors.dart';
import 'package:scam_artist/models/Player.dart';
class PlayerList with ChangeNotifier {
List<Player> _players = [];
List<Player> get players {
return [..._players];
}
void addPlayer(Key key, String name, int index) {
_players.add(
new Player(key: key, color: PlayerColors.colors[index], name: name));
notifyListeners();
}
void editPlayerName(String newName, int index) {
_players[index].name = newName;
notifyListeners();
}
void editPlayerColor(Color newColor, int index) {
_players[index].color = newColor;
notifyListeners();
}
}
However, when I call a function to change a value to one of the Player
objects (change name for example), the list doesn't update the object with new data.
Do I need another provider for the Player
class? If so, how do I make the PlayerList
provider listen for changes in the Player
provider?
Doing a little research, I'm thinking ProxyProvider might be what I'm looking for, but I'm not sure how to implement it.
Here's my Player
class if that is helpful:
import 'package:flutter/material.dart';
class Player {
// id will be for database if implemented
String uid;
Key key;
String name;
//position is the order where the player plays
int position;
Color color;
bool isTurn;
bool isFakeArtist;
bool isWinner;
Player({this.key, this.name, this.color});
}
And this is where I create the ChangeNotifierProvider
:
import 'package:flutter/material.dart';
import 'package:scam_artist/UserListener.dart';
import 'package:scam_artist/models/user.dart';
import 'package:scam_artist/providers/PlayerList.dart';
import 'package:scam_artist/services/AuthService.dart';
import 'package:provider/provider.dart';
import 'package:scam_artist/views/Lobby.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider<User>.value(value: AuthService().user),
ChangeNotifierProvider(create: (context) => PlayerList())
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: UserListener(),
routes: {Lobby.routeName: (ctx) => Lobby()},
),
);
}
}
There are multiple things wrong here.
1. Fix your PlayerList declaration line.
//CORRECT
class PlayerList extends ChangeNotifier {...}
//WRONG
class PlayerList with ChangeNotifier {...}
4. Fix your players getter line.
Use this:
List<Player> get players => _players;
3. You need more Conceptual Knowledge on Provider.
Basically, Provider makes your PlayerList accessible from anywhere within the Widget Tree below where you have provided it. For example, you are providing from the top of your MaterialApp
. So you can access it in your HomePage
or Lobby
.
To access your PlayerList
, you have to use a Consumer
widget or Selector
widget, but for your case, Consumer
is enough. Selector
is for advanced usage.
Here is the code for reading live values from your PlayerList
.
class Lobby extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
body: _body(),
);
_body() => Container(
child: Consumer<PlayerList>(
builder: (BuildContext context, PlayerList bloc) =>
ListView.builder(
itemCount: bloc.players.length,
itemBuilder:
(BuildContext context, int index) => Text(bloc.players[index].name),
),
),
);
}
I am having exactly the same problem.
One way I solved it (not the prettiest though) is to have a method in the ChangeNotifier to return a specific object and then watch for changes, e.g.
// in ChangeNotifier
Player getPlayer(int index) => _players[index];
and then in the widget have
context.watch<PlayerList>().getPlayer(index).updateName("newName")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With