Есть ли у вас опыт работы с Provider во Flutter?

Ответ

Да, Provider был моим основным инструментом для state management в первых Flutter-проектах. Это обёртка над InheritedWidget, которая реализует паттерн поставщика зависимостей (dependency injection) для эффективного распространения и обновления состояния.

Как я его использовал: Чаще всего с ChangeNotifier для реактивности. Создаётся класс модели, который расширяет ChangeNotifier и уведомляет слушателей при изменении состояния.

Пример модели и провайдера:

// Модель состояния
class CartModel with ChangeNotifier {
  final List<Item> _items = [];
  List<Item> get items => List.unmodifiable(_items);

  void addItem(Item item) {
    _items.add(item);
    notifyListeners(); // Критически важный вызов
  }
}

// Инициализация в main.dart
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => CartModel()),
        Provider(create: (_) => SomeOtherService()), // Простой провайдер
      ],
      child: MyApp(),
    ),
  );
}

Потребление состояния в виджете:

// Способ 1: Provider.of с listen: true (по умолчанию)
class CartBadge extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final cart = Provider.of<CartModel>(context); // Виджет перестроится при notifyListeners
    return Text('Items in cart: ${cart.items.length}');
  }
}

// Способ 2: Consumer для оптимизации перестроек
class ProductList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<CartModel>(
      builder: (context, cart, child) {
        // Перестраивается только этот блок
        return ListView.builder(
          itemCount: cart.items.length,
          itemBuilder: (context, index) => ProductItem(cart.items[index]),
        );
      },
    );
  }
}

Мои выводы по Provider:

  • Сильные стороны: Официальная рекомендация от команды Flutter на момент его активного использования, отличная документация, простота для понимания основных концепций DI и реактивности.
  • Идеален для: Небольших и средних приложений, а также для обучения основам управления состоянием. MultiProvider отлично организует глобальные зависимости приложения.
  • Эволюция: Со временем для более сложных сценариев я перешёл на Riverpod, который решает некоторые ограничения Provider (например, работу вне контекста BuildContext).

Ответ 18+ 🔞

Слушай, а вот про Provider я тебе могу рассказать, как про старого доброго друга, с которым уже и не работаешь, но вспоминаешь тепло. Ебать мои старые костыли, это же был мой первый серьёзный инструмент для управления состоянием во Flutter! По сути, хитрая обёртка над InheritedWidget, которая реализует паттерн поставщика зависимостей. Всё гениальное просто — эффективно раскидывает состояние по виджетам и обновляет их, когда надо.

Как я на нём рубился: Чаще всего в связке с ChangeNotifier для реактивности. Создаёшь класс-модель, расширяешь его ChangeNotifier и просто кричишь всем слушателям: «Эй, пацаны, состояние поменялось!» через notifyListeners(). Без этого вызова — нихуя не произойдёт, виджеты так и будут спать, доверия ебать ноль к такой модели.

Смотри, как это выглядело в коде:

// Модель состояния
class CartModel with ChangeNotifier {
  final List<Item> _items = [];
  List<Item> get items => List.unmodifiable(_items);

  void addItem(Item item) {
    _items.add(item);
    notifyListeners(); // Вот эта строчка — святая! Без неё всё насмарку.
  }
}

// Поднимаем всё это дело в main.dart
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => CartModel()),
        Provider(create: (_) => SomeOtherService()), // Простой провайдер без реактивности
      ],
      child: MyApp(),
    ),
  );
}

А вот как потом в виджетах этим пользовались:

// Способ 1: Классический Provider.of. Виджет перестраивается каждый раз при уведомлении.
class CartBadge extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final cart = Provider.of<CartModel>(context); // Слушаем по умолчанию
    return Text('Items in cart: ${cart.items.length}');
  }
}

// Способ 2: Consumer для точечных перестроек, чтобы не дёргать весь виджет.
class ProductList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<CartModel>(
      builder: (context, cart, child) {
        // Перестраивается только этот блок, когда корзина меняется.
        return ListView.builder(
          itemCount: cart.items.length,
          itemBuilder: (context, index) => ProductItem(cart.items[index]),
        );
      },
    );
  }
}

Что я в итоге про него думаю:

  • Что было круто: Официальная рекомендация от самой команды Flutter, ёпта! Документация — огонь, идеально для вкатывания в тему DI и реактивности. MultiProvider — просто песня для организации зависимостей в приложении.
  • Для чего идеален: Для проектов, которые не разрослись до овердохуища бизнес-логики, и для обучения. Осваиваешь базовые принципы — и дальше уже проще.
  • Куда эволюционировал: Со временем для сложных задач я переполз на Riverpod. Тот решает больные мозоли Provider, например, позволяет работать с состоянием где угодно, а не только в контексте виджета. Но начинать-то всё равно с Provider было правильным путём.