我正在尝试使用this example在Flutter中实现登录/注销。登录正常,控制台输出为:
flutter: LOGIN WIDGET BUILD CONTEXT:
flutter: LoginScreen(dirty, state: LoginScreenState#552db)
flutter: _ctx:
flutter: LoginScreen(state: LoginScreenState#552db)
但是注销后,我无法重新登录(上下文丢失)。注销并尝试重新登录后,onAuthStateChanged()
中的上下文在注销后丢失:
flutter: LOGIN WIDGET BUILD CONTEXT:
flutter: LoginScreen(dirty, state: LoginScreenState#d112e)
flutter: _ctx
flutter: LoginScreen
login.dart
class LoginScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new LoginScreenState();
}
}
class LoginScreenState extends State<LoginScreen>
BuildContext _ctx;
@override
onAuthStateChanged(AuthState state) {
print("_ctx");
print(_ctx.toString());
if(state == AuthState.LOGGED_IN) {
print("ready to login");
Navigator.of(_ctx).pushReplacementNamed("/home");
}
}
@override
Widget build(BuildContext context) {
_ctx = context;
print("LOGIN WIDGET BUILD CONTEXT:");
print(_ctx.toString());
}
}
home.dart
class Settings extends StatelessWidget {
@override
Widget build(BuildContext context) => new Container(
child: new ListView(
children: <Widget>[
new ListTile(
//leading: Icon(Icons.map),
title: new Text('About')
),
new ListTile(
//leading: Icon(Icons.photo_album),
title: new Text('Logout'),
onTap: () {
Navigator.of(context).pushReplacementNamed("/login");
}
)
],
),
);
路线:
final routes = {
'/login': (BuildContext context) => new LoginScreen(),
'/home': (BuildContext context) => new Tabs(),
'/' : (BuildContext context) => new LoginScreen(),
};
为什么_ctx
中的onAuthStateChanged()
没有更新,有没有更好的方法来处理登录状态?
答案 0 :(得分:4)
您正在重用旧的BuildContext
实例。不要将实例保存在build
方法中。您永远都不要这样做。
您的LoginScreen
是StatefulWidget
,它的状态(LoginScreenState
)已经具有context
属性。尝试改用它。
您还需要配置侦听器,该示例已经具有可以使用的dispose(AuthListener)
方法。
@override
void dispose() {
super.dispose(); // always call super for dispose/initState
AuthStateProvider().dispose(this);
}
总的来说,这个例子已经很老了,我建议您找到一个最新的教程。 Flutter和Dart的发展非常迅速,要走2年之久的榜样并不是路要走。
答案 1 :(得分:1)
Aman Chu回答,在login_screen.dart和home_screen.dart中都添加以下方法 每当我们切换屏幕时,它都会取消订阅监听器。
@override
void dispose() {
var authStateProvider = new AuthStateProvider();
authStateProvider.unSubscribe(this);
}
此外,您还需要在auth.dart上使用unSubscribe方法,如下所示:
void unSubscribe(AuthStateListener listener) {
for(var l in _subscribers) {
if(l == listener)
_subscribers.remove(l);
}
}
答案 2 :(得分:0)
我为我的应用程序引用了相同的示例,问题是在dispose()期间AuthStateProvider中没有“取消订阅”。尝试在State实施以下内容:
@override
void dispose() {
var authStateProvider = new AuthStateProvider();
authStateProvider.unSubscribe(this);
}