Как использовать поставщика для виджета коммутатора

#flutter #dart

#flutter #dart

Вопрос:

Из примеров и тех, которые я вижу в Интернете, похоже, что с помощью Provider мы можем избежать использования виджетов с отслеживанием состояния для переключения Switch (). Я мог бы добиться этого, используя виджет с отслеживанием состояния, имея глобальную переменную, которую я мог бы установить с помощью setState().

Пример: https://www.tutorialkart.com/flutter/flutter-switch/

Но могу ли я добиться этого в качестве виджета без состояния, используя Provider для виджета коммутатора?

Это мой виджет коммутатора:

 Switch(
  inactiveTrackColor: Colors.greenAccent,
  onChanged: (bool isNoti) {
    Provider.of<Data>(context, listen: false).toggleNotification(isNotifiable: !isNoti);
    print('Noti: $isNoti'); // always prints false
    print('Noti: ${Provider.of<Data>(context, listen: false).isNotifiable}'); // always prints true
  },
  value: Provider.of<Data>(context, listen: false).isNotifiable, // value doesn't change thus no toggle
),
  

Класс данных, используемый поставщиком.

 class Data extends ChangeNotifier {

  bool isNotifiable = false;

  void toggleNotification({bool isNotifiable = true}) {
    this.isNotifiable = isNotifiable;
    notifyListeners();
  }
}
  

Просто чтобы показать его в завершении, я оборачиваю его в ChangeNotifierProvider.

 class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Data>(
      create: (context) => Data(),
      child: ListTile(
        leading: Icon(Icons.notifications),
        title:  Text('Notifications'),
        trailing: Switch(
          inactiveTrackColor: Colors.greenAccent,
          onChanged: (bool isNoti) {
            Provider.of<Data>(context, listen: false).toggleNotification(isNotifiable: !isNoti);
            print('Noti: $isNoti');
            print('Noti Provider: ${Provider.of<Data>(context, listen: false).isNotifiable}');
          },
          value: Provider.of<Data>(context, listen: false).isNotifiable,
        ),
      ),
    );
  }
}
  

Всегда получаю следующий вывод, когда я нажимаю переключатель.

 Noti: false
Noti Provider: true
  

Пожалуйста, посоветуйте. Спасибо.

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

1. В чем именно ошибка? Кажется, все в порядке? Не могли бы вы уточнить проблему?

2. @sameerkashyap Я ожидаю, что переключатель будет переключаться между включением и выключением. Но вместо этого он просто остается включенным, когда я нажимаю переключатель.

Ответ №1:

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

 
trailing: Switch(
          inactiveTrackColor: Colors.greenAccent,
          onChanged: (bool isNoti) {
            Provider.of<Data>(context, listen: false).toggleNotification(isNotifiable: !isNoti);
            print('Noti: $isNoti');
            print('Noti Provider: ${Provider.of<Data>(context, listen: false).isNotifiable}');
          },
          value: Provider.of<Data>(context).isNotifiable,  // remove `listen: false` 
        ),
  

Значение As — это то, от чего зависит восстановление вашего коммутатора. Но провайдер не прослушивает changed, потому что вы упомянули listen: false .

Использование

  • Provider.of<Data>(context, listen: false) когда вы считываете данные, например, в обратных вызовах.
  • Provider.of<Data>(context) используйте это, когда ваш виджет необходимо перестроить, прослушав изменения

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

1. Работает, спасибо. Для тех, кто ссылается на это, также обратите внимание, что при использовании !isNoti возникает ошибка. Это всегда будет false. Вместо этого должно было быть передано значение, обратное значению isNotifiable для моего класса данных.

2. О да, onChanged уже предоставляет значение, которое вам не нужно инвертировать.