Каким образом можно понять, как использовать Provider в Flutter?

Привет! У меня есть несколько вопросов о Flutter и Provider. Я перешел на Flutter из C# и остановился на использовании Provider вместо BLoC, т.к. не понял концепцию BLoC. Можете объяснить мне разницу между ними? Почему некоторые предпочитают BLoC? <br/> Также, я хотел бы узнать, в чем разница между использованием ValueNotifier и ChangeNotifier. Вот как я использую ChangeNotifier в своем сервисе, но недавно увидел пример использования ValueNotifier в библиотеке video_player. Можете пояснить, в чем отличие и какой метод лучше использовать?
  • 12 апреля 2024 г. 18:29
Ответы на вопрос 2
Привет! Давай разберемся.

1. Provider в Flutter используется для управления состоянием приложения и обеспечения доступа к этому состоянию из различных виджетов без необходимости передачи состояния через пропсы. Для того чтобы понять, как использовать Provider, рекомендуется изучить документацию Flutter и примеры кода, доступные в интернете. Примеры практического использования Provider помогут лучше понять его возможности и принцип работы.

2. BLoC (Business Logic Component) - это дополнительный слой между виджетами и источником данных, который обрабатывает бизнес-логику и управляет состоянием приложения. Основное отличие между Provider и BLoC заключается в том, что BLoC предоставляет более гибкий подход к управлению состоянием и позволяет разделять бизнес-логику и представление. Некоторые предпочитают использовать BLoC из-за его мощных возможностей и хорошей масштабируемости.

3. ChangeNotifier и ValueNotifier - это два класса, предоставленные Flutter для уведомления виджетов об изменении состояния объекта. Основное различие между ними заключается в том, что ChangeNotifier предоставляет метод notifyListeners() для уведомления виджетов о изменении состояния, в то время как ValueNotifier имеет свойство value, которое вызывает уведомление при изменении значения. Какой метод лучше использовать зависит от конкретной ситуации и предпочтений разработчика. Если нужно уведомить виджет только при изменении значения, то лучше использовать ValueNotifier. Если требуется более широкий функционал уведомлений, то ChangeNotifier может быть более удобным вариантом.

Надеюсь, это поможет тебе разобраться в теме! Если у тебя остались дополнительные вопросы, не стесняйся задавать их. Удачи с изучением Flutter и Provider!
Если говорить совсем просто, базировано и понятно, то любой виджет во Flutter имеет свой уникальный идентификатор, которым подписываются все действия, исполняемые в нём. Provider присутствует и работает постоянно, но обращаться к нем мы можем, если место использования и место прослушивания имеют некоторый общий родительский виджет Provider. По умолчанию Provider позволяет прослушивать один объект, в котором могут быть как функции, так и переменные, таким образом ChangeNotifier уведомляет о любых изменениях объекта, в то время как NotifierValue прослушивает ровно одну переменную, и уведомляет всех слушателей при изменении ТОЛЬКО этой переменной, это сильно упрощает взаимодействие сложных сценариев приложения. 

Перейдём от разговоров, к применению , рассмотрим на примере настроек пользователя:

class UserProfileProvider with ChangeNotifier {
  String _username;
  String _email;
  bool _isDarkMode;

  UserProfileProvider(this._username, this._email, this._isDarkMode);

  String get username => _username;
  String get email => _email;
  bool get isDarkMode => _isDarkMode;

  void setUsername(String username) {
    _username = username;
    notifyListeners();
  }

  void setEmail(String email) {
    _email = email;
    notifyListeners();
  }

  void toggleTheme() {
    _isDarkMode = !_isDarkMode;
    notifyListeners();
  }
}

Это пример кода, использующего ChangeNotifier, он прослушивает все поля - _username, _email, _isDarkMode

class DoNotDisturbController {
  ValueNotifier<bool> isDoNotDisturbEnabled = ValueNotifier(false);

  void toggleDoNotDisturb() {
    isDoNotDisturbEnabled.value = !isDoNotDisturbEnabled.value;
  }
}

Допустим есть функция "не беспокоить", влияющая на всё приложение целиком.

Код в котором мы будем это использовать:

class SettingsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var userProfileProvider = Provider.of<UserProfileProvider>(context);
    var doNotDisturbController = Provider.of<DoNotDisturbController>(context);

    return Column(
      children: [
        // Для ChangeNotifier
        Text(userProfileProvider.username),
        Switch(
          value: userProfileProvider.isDarkMode,
          onChanged: (value) {
            userProfileProvider.toggleTheme();
          },
        ),

        // Для ValueNotifier
        ValueListenableBuilder<bool>(
          valueListenable: doNotDisturbController.isDoNotDisturbEnabled,
          builder: (context, value, child) {
            return Switch(
              value: value,
              onChanged: (newVal) {
                doNotDisturbController.toggleDoNotDisturb();
              },
            );
          },
        ),
      ],
    );
  }
}

Тут мы можем увидеть, что при изменении ChangeNotifier обновляются сразу все поля и состояния, которые прослушивают КЛАСС, использующий провайдер. В случае с ValueNotifier мы прослушиваем только одну переменную/функцию, что полезно для скорости и простоты использования, НО ограничивает возможности отзывчивости приложения, т.к. мы не обновим целый объект. ChangeNotifier полезен для использования в разветвлении виджетов, применения изменения ряда параметров и работы с объектами в целом, ValueListener полезен для изменения одного конкретного параметра для всего кода. Часто можно избежать применения ValueListener через изменение состояния, т.к. и Provider и setState влияют на данные в BuildContext, но если первый протягивает изменение до слушателя, и меняет состояние из него, то второй применяет изменения на месте.

Таким образом, ChangeNotifier и ValueNotifier обеспечивают разные уровни абстракции и удобства для различных сценариев управления состоянием в Flutter, помогая вам поддерживать чистую и управляемую архитектуру состояния.
Похожие вопросы