#flutter #flutter-provider #flutter-navigation #flutter-change-notifier
#flutter #flutter-provider #flutter-навигация #flutter-change-notifier
Вопрос:
Я новичок в flutter, этот вопрос может быть очень простым. Для реализации этого у меня есть страница авторизации firebase phone, если пользователь вошел в систему, затем перейдите на домашнюю страницу, если пользователь является новым пользователем, затем перейдите на страницу регистрации
Проблема в том, что всякий раз, когда значения изменяются у поставщика, потребитель получает уведомление и перестраивает метод сборки. Я не смогу прослушать их в методе сборки и вернуть Navigator.of(context).pushNamed() . Есть идеи, как правильно использовать ChangeNotifierProvider вместе со слушателями и соответствующей навигацией по страницам?
У меня есть класс входа и класс поставщика, как показано ниже,
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => LoginProvider(),
child: Consumer<LoginProvider>(builder: (context, loginState, child) {
return Scaffold(
...
body: RaisedButton(
onPressed: **loginState.doLogin(_textController.text, context);**
...
)
}),
);
}
}
class LoginProvider with ChangeNotifier {
bool _navigateToSignup = false;
bool get navigateToSignup => _navigateToSignup;
Future doLogin(String mobile, BuildContext context) async {
FirebaseAuth _auth = FirebaseAuth.instance;
_auth.verifyPhoneNumber(
...
verificationCompleted: (AuthCredential credential) async {
UserCredential result = await _auth.signInWithCredential(credential);
User user = result.user;
// if user is new user navigate to signup
// do not want to use Navigator.of(context).pushNamed('/signupPage'); here, instead would like to notify listeners at login page view and then use navigator.
if (user.metadata.creationTime == user.metadata.lastSignInTime) {
_navigateToSignup = true;
} else {
if (result.user != null) {
_navigateToHome = true;
//Navigator.of(context).pushNamedAndRemoveUntil('/homePage', ModalRoute.withName('/'));
}
}
notifyListeners();
},
...
);
}
}
Заранее спасибо.
Ответ №1:
Существует несколько подходов, вы выбираете тот, который подходит вам лучше всего.
-
Передайте
context
ChangeNotifier
, как вы уже делаете. Мне это тоже не нравится, но некоторые люди это делают. -
Передайте обратный вызов вашему
ChangeNotifier
, который будет вызван, когда вам нужно перейти. Этот обратный вызов будет выполнен вашим кодом пользовательского интерфейса. -
То же, что и 2, но вместо обратного вызова экспортируйте a
Stream
и выдайте событие, указывающее, что вам нужно перейти. Затем вы просто слушаете этоStream
в своем пользовательском интерфейсе и переходите оттуда. -
Используйте a
GlobalKey
для своего навигатора и передайте его своемуMaterialApp
, чем вы можете использовать этот ключ везде. Подробнее здесь.
Комментарии:
1. Спасибо, я подумал о 3-м пункте и попробовал ниже .. это работает.. Страница входа в систему имеет ниже void _navigationController() { _loginProvider.gotoHomePage.stream.listen((событие) { Navigator.of(context).pushNamed(‘/homePage’) } и у провайдера будет StreamController<bool> _gotoHomePage = StreamController<bool>(); StreamController<bool> получить gotoHomePage => _gotoHomePage;
2. Обычно я выбираю вариант 2, поскольку мне не нужно иметь дело со сложностями потоков, такими как не забыть отменить подписку и немного более сложный код… Но все варианты имеют свое место.