StatelessWidget и ScrollController

#flutter #dart

#флаттер #dart

Вопрос:

У меня есть StatelessWidget во flutter ScrollController , у которого есть дочерний компонент этого компонента, который я StatefulWidget добавляю scrollController.addListener в его initState

 
class MyStatelessWidget extends StatelessWidget {
  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Placeholder(), //Complex child
        Placeholder(), //Complex child
        Placeholder(), //
        MyStatefulWidget(
          scrollController: scrollController,
        ) // Complex child
      ],
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  final ScrollController scrollController;

  const MyStatefulWidget({
    @required this.scrollController,
  });

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

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    print('Scroll listener added');
    widget.scrollController.addListener(() {
      print('Scroll position changed');
    });
    super.initState();
  }
}
 

Моя проблема в том, что при build выполнении родительского MyStatelessWidget элемента иногда я терял прослушиватель прокрутки
Почему? и как я могу это исправить?

Ответ №1:

_myStatefulWidget вызывает build , но нет initState . Следовательно, вы не регистрируете прослушиватель на новом контроллере.

Решением было бы использовать решение для управления состоянием, чтобы разделить контроллер между виджетами. Проверьте пакет поставщика.

Комментарии:

1. это происходит и в производственном приложении

2. Решение по-прежнему заключается в использовании решения для управления состоянием. Я рекомендую вам начать с Provider, если управление состоянием для вас ново. Хотя есть и другие варианты, такие как bloc или redux.

3. Я уверен, что addListener это вызвано, но проблема в final ScrollController scrollController = ScrollController(); повторно создается

4. Правильно. Я говорю, что addListener это не вызывается для нового объекта после повторного создания экземпляра. Виджет без состояния создается только один раз, поэтому, когда он «перестраивается», он фактически создается заново, поэтому с ним происходит то же scrollController самое. Однако виджет с отслеживанием состояния может быть перестроен без повторного создания экземпляра. Следовательно, initState не вызывается, и, следовательно, слушатель не добавляется к новому scrollController .

5. Быстрое решение — создать _myStatelessWidget виджет с отслеживанием состояния. Тогда он может перестроиться без повторного создания экземпляра scrollController , но это не поможет вам понять нюансы Stateful vs. Виджеты без состояния.