如何使用颤振提供者监听列表中的变化?

Posted

技术标签:

【中文标题】如何使用颤振提供者监听列表中的变化?【英文标题】:How to listen for change within a list using flutter provider? 【发布时间】:2020-09-19 03:27:52 【问题描述】:

我有一个提供程序正在监听 playerList 类的更改:

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

但是,当我调用函数将值更改为 Player 对象之一(例如更改名称)时,列表不会使用新数据更新对象。

Player 类是否需要另一个提供程序?如果是这样,我如何让PlayerList 提供者监听Player 提供者的变化?

做了一些研究,我认为 ProxyProvider 可能是我正在寻找的东西,但我不确定如何实现它。

如果有帮助,这是我的 Player 课程:

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

这就是我创建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(),
      ),
    );
  

【问题讨论】:

我也有同样的问题。你有没有设法修复它?我已经尝试将notifyListeners() 发送到列表的每个对象,并在我执行更新时调用它,但行为仍然存在。有任何想法吗?另外,我目前正在将 ProxyProvider 用于其他事情,并且可以正常工作,但那是为了让一个提供者监听另一个提供者的更改,我不知道如何创建提供者的动态列表(播放器)来使用它们方式。 【参考方案1】:

这里有很多问题。

1.修复您的 PlayerList 声明行。

//CORRECT
class PlayerList extends ChangeNotifier ...
//WRONG
class PlayerList with ChangeNotifier ...

4.修正你的球员吸气剂线。

使用这个:

List<Player> get players => _players;

3。您需要更多关于提供者的概念知识。

基本上,Provider 使您的 PlayerList 可以从您提供它的下方小部件树中的任何位置访问。例如,您从MaterialApp 的顶部提供。所以你可以通过HomePageLobby 访问它。

要访问您的PlayerList,您必须使用Consumer 小部件或Selector 小部件,但对于您的情况,Consumer 就足够了。 Selector 用于高级用途。

这是从您的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),
          ),
    ),

  );


【讨论】:

【参考方案2】:

只需更改您的 _players 访问器,您应该会很好。

  List<Player> get players 
    return _players;
  

【讨论】:

【参考方案3】:

我也遇到了同样的问题。

我解决它的一种方法(虽然不是最漂亮的)是在 ChangeNotifier 中有一个方法来返回一个特定的对象,然后观察变化,例如

// in ChangeNotifier

Player getPlayer(int index) => _players[index];

然后在小部件中有

context.watch<PlayerList>().getPlayer(index).updateName("newName")

【讨论】:

以上是关于如何使用颤振提供者监听列表中的变化?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用颤振在firebase中进行查询?

知道应用程序内部的信息作为另一个类中的列表存在,我如何在颤振中使用搜索

vue中如何监听vuex中的数据变化

如何使用 ESP8266 监听 Firestore 的变化?

如何将模型列表复制到颤振中的新列表?

如何从firebase颤振中的文档中检索列表?