Виджет не перерисовывается при изменении переменной Provider - Flutter

avatar
MIPB
8 августа 2021 в 16:11
205
1
0

У меня есть провайдер под названием "FavoritesProvider", у которого есть переменная "_favoritos", в которой я храню список идентификаторов.

Что я пытаюсь сделать, так это перерисовывать виджет ListView каждый раз, когда в переменную избранного добавляется или удаляется новый элемент. Вот функция, в которой я это делаю, где я обновляю переменную и уведомляюListeners.

    Future setFavorites(
    int id,
  ) async {
    final prefs = await SharedPreferences.getInstance();
    String _receivedData = (prefs.getString('favorites') ?? "");
    List _decodedData = [];
    if (_receivedData != "") {
      _decodedData = json.decode(_receivedData);
    }
    String _sentData = "";

    if (_decodedData.contains(id)) {
      _decodedData.remove(id);
      _sentData = json.encode(_decodedData);
    } else {
      _decodedData.add(id);
      _sentData = json.encode(_decodedData);
    }

    prefs.setString("favorites", _sentData);
    _favoritos = _decodedData;
    notifyListeners();
    return _favoritos;}

Элемент, который я пытаюсь перерисовать, вложен следующим образом:

  • MainPage: каркасное тело, содержащее IndexedStack
  List<Widget> _widgetOptions = [
    HomePage(),
    FavoriteScreen(),
    CompletedScreen()
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: IndexedStack(
          index: _selectedIndex,
          children: _widgetOptions,
        ),
  • FavoriteScreen: виджет без статистики, содержащий только мой собственный виджет FavDoneList.
  • FavDoneList: виджет с отслеживанием состояния, содержащий список. -> Я хочу перерендерить его. Я пытался использовать прослушиватель, но он не перерисовывается:
  @override
  Widget build(BuildContext context) {
    var _favorites = Provider.of<FavoritesProvider>(context).favoritos;

    if (flag == true) {
      if (_favorites.isEmpty) {
        return Center(child: Text("No has añadido favoritos"));
      }

      return ListView(
        children: _loadFavorites(_favorites),
      );
    }
    return Center(
        child: CircularProgressIndicator(
      color: Colors.red,
    ));
  }

Можете ли вы помочь мне понять, что я делаю неправильно? Не могу понять как перерисовать. Спасибо!

Источник
David
8 августа 2021 в 19:29
0

Пожалуйста, добавьте сообщение об ошибке или какое-либо указание на то, в чем проблема. Спасибо!

MIPB
8 августа 2021 в 21:30
0

Нет сообщения об ошибке @David, просто виджет не обновляется, как можно было бы ожидать от провайдера, но, несмотря на это, он работает нормально!

David
9 августа 2021 в 03:00
0

Я не вижу виджет провайдера нигде в вашем дереве виджетов. Вы используете правильную версию (вероятно, ChangeNotifierProvider)? Если да, можете ли вы добавить больше дерева виджетов, чтобы включить это?

David
9 августа 2021 в 03:03
0

Кроме того, вы не показываете, как/где вы вызываете setFavorites, это тоже может быть полезно. Вы уверены, что базовые данные действительно меняются? Попробуйте добавить точку останова и проверить, действительно ли _decodedData содержит новую информацию.

MIPB
9 августа 2021 в 08:04
0

@ Дэвид, да, извини. ChangeNotifierProvider находится в корне моего приложения, поэтому он должен передавать информацию всем компонентам внутри моего приложения. setFavorites вызывается отдельной кнопкой в ​​другом виджете. Но это работает, потому что когда я перезагружаю приложение, страница обновляется. :/ Сегодня я постараюсь обновить свой вопрос, извините за путаницу.

Ответы (1)

avatar
MIPB
22 августа 2021 в 20:05
0

Я решил это, используя что-то "уродливое":

Поскольку ни один из моих провайдеров, потребителей или слушателей не работал, я стремился перезагружать весь виджет FavDoneList каждый раз, когда нажималась средняя нижняя вкладка. Это была очень небольшая цена с точки зрения производительности, и это не сильно повлияет на пользователя.

Я сделал вот так на главной странице:

  void _onItemTapped(int index) {
if (index == 1) {
  setState(() {
    _widgetOptions.removeAt(1);
    _widgetOptions.insert(1, FavDoneList(key: UniqueKey()));

    _selectedIndex = index;
  });
} else {
  setState(() {
    _selectedIndex = index;
  });
}}

Очень важно передать уникальный ключ, иначе он не будет работать.