Flutter: Provider: ListView не перерисовывается после notifyListener()

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

Почему Provider не может инициировать перерисовку ListView после выполнения вызова notifyListeners.

Упрощенный пример кода (сегмент данных):

class TheData extends ChangeNotifier {
   List<ListTile> data = [
      ListTile(title: Text('A')),
   ];

   addTile() {
      data.add(ListTile(title: Text('B')));
      notifyListeners();
   }
}

Скрин с использованием TheData:

class TheScreen extends StatefulWidget {
  @override
  TheScreenState createState() => TheScreenState();
}

class TheScreenState extends State<TheScreen> {
  @override
  Widget build(BuildContext context) {
    return Consumer<TheData>(
       builder: (ctx, _theData, _) {
           print('rebuilding count = ${_theData.data.length}');
           return ListView(
              children: _theData.data,
           );
       }
    );
  }
}

Предположим, что класс TheData правильно предоставлен над этим экраном в дереве виджетов и что я запустил 'addTile()'. Печать показывает, что теперь в «данных» есть 2 элемента, но ListView не меняется.

Это сводит меня с ума.


person Maksym Moros    schedule 19.05.2020    source источник


Ответы (1)


Я понятия не имею, почему это имело значение или менее эффективно... Однако использование ListView.builder() устраняет проблему:

class TheScreen extends StatefulWidget {
  @override
  TheScreenState createState() => TheScreenState();
}

class TheScreenState extends State<TheScreen> {
  @override
  Widget build(BuildContext context) {
    return Consumer<TheData>(
       builder: (ctx, _theData, _) {
           print('rebuilding count = ${_theData.data.length}');
           return ListView.builder(
              itemCount: _theData,data.length,
              itemBuilder: (c, i) => _theData.data[i],
           );
       }
    );
  }
}
person Maksym Moros    schedule 19.05.2020
comment
У меня такая же проблема. Проблема в том, что Flutter использует неизменяемые объекты. Таким образом, хотя базовые данные изменяются, ListView не замечает необходимости перерисовки, поскольку ссылка не изменилась. - person Maksym Moros; 25.05.2020