Трепетание с помощью StreamProvider для установки состояния - PullRequest
0 голосов
/ 29 марта 2020

Я скопировал с помощью StreamProvider из этого урока: https://github.com/iamshaunjp/flutter-firebase

У меня есть класс для отдельных предметов, таких как:

class PostItem extends StatefulWidget {
  PostItem({Key key, @required this.post}) : super(key: key);

  final Post post;

  @override
  _PostItemState createState() => _PostItemState();
}

class _PostItemState extends State<PostItem> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return getCard(context);
  }

  Widget getCard(context) {
    return Card(
      child: InkWell(
        onTap: _didSelectItem,
        child: Row(
          children: [
            _textColumn(context),
            _voteColumn(context),
          ],
        ),
      ),
    );
  }

  Widget _textColumn(context) {
    return Expanded(
      child: Container(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              child: Text(
                widget.post.title,
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
              ),
              padding: const EdgeInsets.fromLTRB(16, 16, 0, 0),
            ),
            BottomButtonBar(
              onLikedPressed: () => _didLikePost(),
              // likeColor: _likedPids.contains(widget.post.pid)
              //     ? Theme.of(context).primaryColor
              //     : Theme.of(context).accentColor,
            ),
          ],
        ),
      ),
    );
  }

  Widget _voteColumn(context) {
    final user = Provider.of<User>(context);
    final post = widget.post;

    return VoteColumn(
        upArrowColor:
            Vote.getVote(user.uid, post.upvoteUids, post.downvoteUids) ==
                    Vote.up
                ? Theme.of(context).primaryColor
                : Theme.of(context).focusColor,
        downArrowColor:
            Vote.getVote(user.uid, post.upvoteUids, post.downvoteUids) ==
                    Vote.down
                ? Theme.of(context).primaryColor
                : Theme.of(context).focusColor,
        didVote: (val) => _didVote(val),
        value: widget.post.upvoteUids.length - widget.post.downvoteUids.length);
  }

  //Mark: Private
  _didLikePost() {
    print("called");
    setState(() {});
    // _dbLikePost();
  }

  _dbLikePost() async {
    // final userMetadata = Provider.of<UserMetadata>(context);
    // try {
    //   Database().updateUserMetadata(userMetadata);
    // } catch (error) {
    //   print(error);
    // } finally {}
  }

  _didSelectItem() {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (BuildContext context) => Comments(post: widget.post),
      ),
    );
  }

  //true for up, false for down
  _didVote(bool newVote) {
    setState(() {
      _locatUpdate(newVote);
    });
    _dbUpdate();
  }

  _locatUpdate(newVote) {
    final user = Provider.of<User>(context);
    final uid = user.uid;
    final post = widget.post;
    switch (Vote.getVote(user.uid, post.upvoteUids, post.downvoteUids)) {
      case Vote.up:
        if (newVote) {
          post.upvoteUids.remove(uid);
        } else {
          post.upvoteUids.remove(uid);
          post.downvoteUids.add(uid);
        }
        break;
      case Vote.down:
        if (newVote) {
          post.downvoteUids.remove(uid);
          post.upvoteUids.add(uid);
        } else {
          post.downvoteUids.remove(uid);
        }
        break;
      case Vote.none:
        if (newVote) {
          post.upvoteUids.add(uid);
        } else {
          post.downvoteUids.add(uid);
        }
        break;
    }
  }

  _dbUpdate() async {
    try {
      await Database().post(widget.post);
    } catch (error) {
      print(error);
    } finally {}
  }
}

Вот где я чрезвычайно смущенный. Я могу изменить widget.post и вызвать setState, и это прекрасно работает. Я также могу использовать widget.post для обновления поста в БД. Работает отлично, как я и ожидаю.

Теперь я хочу обновить userMetadata, который я поместил в поток выше.

 Widget build(BuildContext context) {
    final user = Provider.of<User>(context);

    return user == null
        ? MaterialWidget(home: AuthView())
        : StreamProvider<UserMetadata>.value(
            value: Database(id: user.uid).userMetadata,
            catchError: (_, error) => UserMetadata(uid: ""),
            child: MaterialWidget(
              home: Home(
                title: "Siren",
              ),
            ),
          );
  }

Я просто хочу установить состояние PostItem страница и изменить БД при нажатии кнопки «Нравится». Я хочу сделать это, используя UserMeta от поставщика потоков. Тем не менее, если я пытаюсь сделать это, я получаю сообщение об ошибке «Неподдерживаемая операция: невозможно добавить в неизменяемый список». Почему я получаю эту ошибку при попытке отредактировать потокового провайдера, но не для поста? Как правильно отредактировать список, установить его на место, а затем положить в базу данных sh?

...