Управление состоянием провайдера флаттера, концепция выхода из системы
Я пытаюсь реализовать индивидуальное решение для выхода из системы для своего приложения, где бы ни находился пользователь, как только Logout button
нажата, приложение вернется к Login page
.
Моя идея заключалась в том, что вместо того, чтобы прослушивать каждый компонент для изменения состояния, у меня был бы один единственный слушатель на главном компоненте -> MyApp
.
Для простоты я сократил элементы до минимума. Вот как мог бы выглядеть мой класс Profile:
class Profile with ChangeNotifier {
bool _isAuthentificated = false;
bool get isAuthentificated => _isAuthentificated;
set isAuthentificated(bool newVal) {
_isAuthentificated = newVal;
notifyListeners();
}
}
Теперь под Main
, Я зарегистрировал этого провайдера следующим образом:
void main() => runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => Profile(),
)
],
child: MyApp(),
),
);
И наконец MyApp
составная часть:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Consumer<Profile>(
builder: (context, profile, _) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Color.fromARGB(255, 0, 121, 107),
accentColor: Color.fromARGB(255, 255, 87, 34),
),
home: buildBasePage(context, profile),
);
},
);
}
Widget buildBasePage(BuildContext context, Profile currentProfile) {
return !currentProfile.isAuthentificated
? LoginComponent()
: MyHomePage(title: 'Flutter Demo Home Page test');
}
}
Моя идея заключалась в том, что как MyApp
компонент является мастером, я должен иметь возможность создать потребителя, который будет уведомлен, если текущий пользователь аутентифицирован, и отреагирует соответствующим образом.
Что происходит, когда я, например, MyHomePage
компонент и я нажимаю Logout()
метод, который выглядит следующим образом:
void _logout() {
Provider.of<Profile>(context, listen: false).isAuthentificated = false;
}
Я ожидал, что при изменении свойства начальный MyApp
компонент будет реагировать и генерировать LoginPage
; что не так. Я пытался сменитьConsumer
к Provider.of<Profile>(context, listen: false)
но с тем же результатом.
Что мне нужно сделать, чтобы эта концепция заработала? Это вообще правильно делать так?
Я имею в виду, что я бы точно мог обновить свой Profile
class таким образом, что я добавляю следующий метод:
logout(BuildContext context) {
_isAuthentificated = false;
Navigator.push(
context, MaterialPageRoute(builder: (context) => LoginComponent()));
}
А потом просто позвони Provider.of<Profile>(context, listen: false).logout()
, однако я думал, что пакет Provider был разработан для этого... или я что-то упускаю?
Любая помощь в этом вопросе будет более чем оценена.
2 ответа
Я не знаю, почему у тебя это не сработало. Вот полный пример, который я построил на основе вашего описания. Оно работает!
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Profile with ChangeNotifier {
bool _isAuthentificated = false;
bool get isAuthentificated {
return this._isAuthentificated;
}
set isAuthentificated(bool newVal) {
this._isAuthentificated = newVal;
this.notifyListeners();
}
}
void main() {
return runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<Profile>(
create: (final BuildContext context) {
return Profile();
},
)
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Consumer<Profile>(
builder: (final BuildContext context, final Profile profile, final Widget child) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: profile.isAuthentificated ? MyHomePage() : MyLoginPage(),
);
},
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Home [Auth Protected]")),
body: Center(
child: RaisedButton(
child: const Text("Logout"),
onPressed: () {
final Profile profile = Provider.of<Profile>(context, listen: false);
profile.isAuthentificated = false;
},
),
),
);
}
}
class MyLoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Login")),
body: Center(
child: RaisedButton(
child: const Text("Login"),
onPressed: () {
final Profile profile = Provider.of<Profile>(context, listen: false);
profile.isAuthentificated = true;
},
),
),
);
}
}
Вам не нужно проходить listen:false
вместо этого просто позвоните
Provider.of<Profile>(context).logout()
Итак, ваш класс профиля будет выглядеть так
class Profile with ChangeNotifier {
bool isAuthentificated = false;
logout() {
isAuthentificated = false;
notifyListeners();
}
}