如果令牌已在 Flutter 中过期,我正在尝试重定向到登录
尝试获取帖子:
body: new Container(
padding: new EdgeInsets.only(bottom: 8.0),
color: Color(0xff2c3e4e),
child: FutureBuilder<List<Post>>(
future: api.getposts(),
builder: (context, snapshot) {
// doing stuff with response
}
)
)
Run Code Online (Sandbox Code Playgroud)
getposts 并捕获错误:
Future<List<Post>> getposts() async {
url = 'url';
var response = await http.get(url,
headers: {HttpHeaders.authorizationHeader: 'bearer ' + token},
);
//part I can't understand how to get to work, how do I push? This gives error about context not being defined.
if (response.body.toString().contains('Token is Expired')) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LoginScreen()),
);
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,在这种情况下我如何正确使用 Navigator 并且我可以重定向回 loginScreen 以防令牌已过期并需要更新?就像代码示例中的注释中提到的那样,上下文给了我“未定义”。
这甚至可能是我做的方式还是我只是处理整个检查完全错误?
代码应该具有单一职责。你的getPost方法同时做两件事。您应该中断此函数,以便它成功获取帖子或抛出异常,并且其调用者将处理异常。顺便说一句,它的调用者必须在build方法内,因为只有build方法有BuildContext context,如下所示:
if (response.body.toString().contains('Token is Expired')) {
throw new Exception("Token is Expired") // you may want to implement different exception class
}
Run Code Online (Sandbox Code Playgroud)
body: new Container(
padding: new EdgeInsets.only(bottom: 8.0),
color: Color(0xff2c3e4e),
child: FutureBuilder<List<Post>>(
future: api.getposts(),
builder: (context, snapshot) {
if (snapshot.hasError) {
// you might want to handle different exception, such as token expires, no network, server down, etc.
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
);
return Container(); // return empty widget
}
if (snapshot.hasData) {
// do somthing with data
return Text('Some data here');
}
// has no data
return Text("Loading...");
}),
),
Run Code Online (Sandbox Code Playgroud)
更新
感谢@TruongSinh,我明白了。
按照他的示例,找出了有效的构建导航器方法:
if (snapshot.hasError) {
@override
void run() {
scheduleMicrotask(() {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
);
});
}
run();
}
Run Code Online (Sandbox Code Playgroud)
我这样做是为了StreamBuilder对变化做出反应,并且当我们还不知道用户是否已连接时能够显示加载屏幕。
StreamBuilder authGuard = StreamBuilder(
stream: Auth.authState$,
builder: (context, snapshot) {
switch (snapshot.data) {
case AuthState.PENDING:
return LoadingScreen();
case AuthState.UNAUTHENTICATED:
return SignInScreen();
case AuthState.AUTHENTICATED:
return HomeScreen();
default:
return LoadingScreen();
}
},
);
Run Code Online (Sandbox Code Playgroud)
因此它会根据 AuthState 改变屏幕:
return MaterialApp(
// ...
home: authGuard,
);
Run Code Online (Sandbox Code Playgroud)