Предисловие:
Provider — теперь официально рекомендуемый метод управления состоянием, объявленный на конференции Google I/O 2019. Я чувствую себя очень хорошо после изучения и использования его, потому что он действительно прост в использовании, поэтому я напишу блог, чтобы записать его! !
Адрес провайдера на GitHub:GitHub.com/Замешиваем кислый мерзавец…
Выложи еще два видео на тюбинг (в первом речь идет только о ChangeNotifierProvider, а не о MultiProvider):
woohoo.YouTube.com/watch?V=как CS…
woohoo.YouTube.com/watch?V='s_no…
Хорошо, не много глупостей. Давайте посмотрим, как использовать Provider для управления состоянием во Flutter.
Я покажу вам, как использовать Provider для управления состоянием с помощью небольшой демонстрации. Используйте одиночные реализации Provider и MultiProvider соответственно (первая помещает оба данных в один и тот же класс, вторая разбивает эти два данных на два разных класса).
Функция этой демонстрации очень проста: считать + переключать тему. Есть только две страницы, и обе страницы используют одни и те же данные.
Я загрузил код этой небольшой демонстрации на GitHub:GitHub.com/M зона cl/грипп… (MultiProvider) GitHub.com/M зона cl/грипп…(Единый провайдер)
Взгляните на следующие рендеры:
Давайте поговорим о том, как один и несколько провайдеров реализуют вышеуказанные функции соответственно.
1. Случай одного провайдера
Можно сказать, что ChangeNotifierProvider является своего рода Provider. Его удобно использовать для управления ситуациями, когда есть только один общий класс данных.
Шаг 1: Добавьте зависимости
Добавьте зависимости в файл pubspec.yaml.
адрес паба пакета провайдера:Universal.Dev/packages/cheat...
Шаг 2: Создайте общие классы данных
class DataInfo with ChangeNotifier {
int _count = 0;
ThemeData _themeData = ThemeData.light();
get count => _count;
get themeData => _themeData;
addCount() {
_count++;
notifyListeners();
}
subCount() {
_count--;
notifyListeners();
}
changeTheme() {
if (_themeData == ThemeData.light()) {
_themeData = ThemeData.dark();
} else {
_themeData = ThemeData.light();
}
notifyListeners();
}
}
Классы данных должны с ChangeNotifier уведомлять слушателей об обновлении интерфейса с помощью функции notifyListeners().
Шаг 3: Получите доступ к данным
Провайдер может получить статус данных двумя способами:
- Использовать Provider.of
(контекст) - Использовать потребительский
Однако эти два способа нуждаются в ChangenotifierProvider():
1. Используйте Provider.of(контекст)
Например, код для указания тематического раздела выглядит следующим образом:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var dataInfo = Provider.of<DataInfo>(context);
return MaterialApp(
home: MyHomePage(),
theme: dataInfo.themeData,
);
}
}
Чтобы получить экземпляр DataInfo через Provider.of
2. Используйте потребителя
Аналогично возьмем в качестве примера код указанного тематического раздела:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<DataInfo>(
builder: (context, dataInfo, _) => MaterialApp(
home: MyHomePage(),
theme: dataInfo.themeData,
),
);
}
}
Непосредственно оберните виджет, который должен использовать общие данные с потребителем. Точно так же потребитель также должен указать тип.
2. Используйте MultiProvider для управления несколькими классами общих данных.
Это можно использовать с потоком. Для объяснения, связанного с потоком, у этого большого парня (@Vadaski) есть отличная статья:nuggets.capable/post/684490…
Шаг 1: Добавьте зависимости
То же, что и выше, но добавьте пакет провайдера.
Шаг 2: Создайте общие классы данных
Здесь я создал два класса: CounterBloc и ThemeDataBloc для управления значением счетчика и ThemeData соответственно. (Как видно из названия класса, оно фактически заимствовано из идеи BLoC)
class CounterBloc {
StreamController<int> _streamController;
Stream<int> _stream;
int _count;
CounterBloc() {
_count = 0;
_streamController = StreamController.broadcast();
_stream = _streamController.stream;
}
Stream<int> get stream => _stream;
int get count => _count;
addCounter() {
_streamController.sink.add(++_count);
}
subCounter() {
_streamController.sink.add(--_count);
}
dispose() {
_streamController.close();
}
}
Поскольку CounterBloc осуществляет мониторинг на обеих страницах, _streamController здесь должен быть широковещательного типа и должен поддерживать несколько подписок, иначе будет сообщено об ошибке.
class ThemeDataBloc {
StreamController<ThemeData> _streamController;
Stream<ThemeData> _stream;
ThemeData _themeData;
ThemeDataBloc() {
_themeData = ThemeData.light();
_streamController = StreamController();
_stream = _streamController.stream;
}
Stream<ThemeData> get stream => _stream;
changeTheme() {
_themeData = _themeData == ThemeData.light()?ThemeData.dark():ThemeData.light();
_streamController.sink.add(_themeData);
}
dispose() {
_streamController.close();
}
}
Из-за используемого здесь Stream нет необходимости в ChangeNotifier, как указано выше.
Шаг 3. Разместите MultiProvider на верхнем уровне приложения.
У MultiProvider есть обязательный параметр: provider, нам нужно передать ему список провайдеров. Таким образом, мы можем получить доступ к связанным общим данным во всех дочерних виджетах.
main() {
var counterBloc = CounterBloc();
var themeDataBloc = ThemeDataBloc();
runApp(MultiProvider(providers: [
Provider<CounterBloc>.value(value: counterBloc),
Provider<ThemeDataBloc>.value(value: themeDataBloc),
], child: MyApp()));
}
Шаг 4: Получите доступ к данным
Используйте Provider.of
Или возьмем в качестве примера код, определяющий тему:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder(
builder: (context, snapshot) {
return MaterialApp(
home: MyHomePage(),
theme: snapshot.data,
);
},
initialData: ThemeData.light(),
stream: Provider.of<ThemeDataBloc>(context).stream,
);
}
}
Также необходимо указать тип после функции для поиска конкретного провайдера.
Ну, это основное использование Provider во Flutter для управления состоянием!