Я использую пакет Provider для работы с данными из разных мест. Для этого вопроса я создал образец проекта, который состоит из экрана приветствия, на котором отображается кнопка входа в систему, после щелчка он перенаправляется на экран входа в систему, где будет текстовое поле входа в систему, но на данный момент я разместил кнопку, которая при вызове щелчка функция входа в систему и эта функция входа в систему уведомляет слушателей. У меня также есть функция выхода из системы и логическое значение, которое отслеживает статус входа в систему.
Эти функции и значения находятся в файле с именем auth.provider.dart
в каталоге поставщиков в папке lib.
import 'package:flutter/foundation.dart';
class Auth with ChangeNotifier {
var _loggedIn = false;
bool get loggedIn => _loggedIn;
void loginUser() {
_loggedIn = true;
print('Logged in');
notifyListeners();
}
void logout() {
_loggedIn = false;
print('Logged out');
notifyListeners();
}
}
Я предоставляю поставщика в main.dart, а также использую Consumer:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Auth>(
create: (_) => Auth(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Consumer<Auth>(
builder: (_, auth, __) {
print('main.dart logged in: ${auth.loggedIn}');
if(auth.loggedIn) return HomeScreen();
return WelcomeScreen();
},
),
routes: {
LoginScreen.routeName: (ctx) => LoginScreen(),
HomeScreen.routeName: (ctx) => HomeScreen(),
},
),
);
}
}
В приведенном выше файле я просто проверяю, является ли loggedIn
истинным или нет. Если это не так, покажите экран приветствия, чтобы пользователь мог войти в систему, но если пользователь вошел в систему, тогда сразу покажите главный экран. Также поместите оператор печати в конструктор Consumer, чтобы он печатал статус всякий раз, когда он получает уведомление о любых изменениях в данных аутентификации. Это выполняется один раз при запуске приложения и никогда больше.
На экране входа в систему не так много всего, только скаффолд и кнопка входа в систему, которая вызывает функцию входа.
RaisedButton(
child: Text('Click to Login'),
onPressed: () {
Provider.of<Auth>(context, listen: false).loginUser();
},
),
Теперь по нажатие кнопки входа в систему устанавливает для логического loggedIn
значение true и уведомляет слушателя, который должен быть Consumer, но Consumer в main.dart никогда не уведомляется об этом. Это не вызывает изменения, существует условие, которое проверяет, является ли вход в систему истинным, затем показывает главный экран, но экран вообще не меняется. Чтобы перейти на главный экран, нужно вручную использовать Navigator
, а на главном экране есть кнопка выхода из системы, которая просто устанавливает для loggedIn
значение false, как только это произойдет, он должен уведомить Потребителя, но это снова не так.
Это подводит меня к вопросу: как работают слушатели в Provider? Когда он уведомляет слушателей об изменениях? Не будет ли он уведомлять, если изменения происходят более чем на один уровень ниже, как в приведенном выше примере, Consumer находится в main.dart, а изменения происходят на 2 уровня ниже main.dart > WelcomeScreen > LoginScreen
. Как сообщить Потребителю в main.dart
, что базовые данные, которые он использует, изменились?
Если вы хотите быстро начать работу с приведенным выше примером, здесь - это ссылка на репозиторий.