更新继承的小部件变量的值
Update value of variable of inherited widget
这是我正在制作的应用程序的登录代码。我想更新 parent_inherit(Inherited Widget) 中的令牌,这是我在发布 request.But 后得到的 我无法理解如何在没有该构建方法的情况下显式更新 Inherited widget 变量的值或 parent_inherit widget.I 想要更改 Inherited widget(parent_inherit) 中的标记值。
Future<void> attemptLogIn(String username, String password,BuildContext context) async {
String parentToken= parent_inherit.of(context);
SharedPreferences prefs = await SharedPreferences.getInstance();
print("$username $password");
final http.Response res = await http.post(
"..............the route.............",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
"email": username,
"password": password
}),
);
if(res.statusCode == 200) {
prefs.setString('jwt',res.body);
var value=prefs.getString('jwt');
Map<String,dynamic> valueMap=jsonDecode(value);
TokenClass token=TokenClass.fromJson(valueMap);
parentToken=token.token;// I was trying something like this,but it seems to not work
Navigator.of(context).pushNamed('/home');
}
else{
return _showMyDialoglogin(context,res.statusCode);
}
}
此外,在上面的文件中,当我在上面声明 parentToken 并向下使用它时,它仍然显示上面声明的 parentToken 不是 used.It 当我将鼠标悬停在 it.Why 上时也会显示警告,所以?
parent_inherit.dart
class parent_inherit extends InheritedWidget {
final String token;
const parent_inherit({
Key key,
@required this.token,
Widget child})
:super(key:key,child: child);
@override
bool updateShouldNotify(parent_inherit oldWidget) =>true;
static String of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<parent_inherit>().token;
}
TokenClass.dart
class TokenClass{
final String token;
TokenClass(this.token);
TokenClass.fromJson(Map<String,dynamic> json)
: token=json['token'];
}
我的主要功能 - 在主要功能中,令牌值存在问题,它无法正确更新和获取继承内部和外部的值 widget.Sometimes 它也使用以前的令牌值。
main.dart
bool checkingKey;
String tokenName;
TokenClass token;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Paint.enableDithering = true;
const defaultJson = '{}';
var prefs = await SharedPreferences.getInstance();
checkingKey = prefs.containsKey("jwt");
tokenName=prefs.getString('jwt');
Map<String, dynamic> valueMap = jsonDecode(tokenName??defaultJson);
token=TokenClass.fromJson(valueMap);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return parent_inherit(
token: checkingKey==false?'':token.token,
child: MaterialApp(
home: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
color: Color(0xffccffcc),
child: !checkingKey ? LoginPage() : mainPage(),
),
),
),
routes: <String,WidgetBuilder>{
'/home':(BuildContext context) => mainPage(),
'/login':(BuildContext context) => LoginPage(),
},
),
);
}
}
也欢迎其他建议...
更新 InheritedWidget
的一种方法是使用 Notification
。
首先,我们有通知Class:
class LoginNotification extends Notification {
final TokenClass token;
LoginNotification(this.token);
}
然后我们用通知侦听器包装 parent_inherit
:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return NotificationListener<LoginNotification>(
onNotification: (loginNotification) {
setState(() {
token = loginNotification.token;
checkingKey = true;
});
return true;
},
child: parent_inherit(
token: checkingKey ? token.token : '',
child: MaterialApp(
home: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
color: Color(0xffccffcc),
child: checkingKey ? MainPage() : LoginPage(),
),
),
),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => MainPage(),
'/login': (BuildContext context) => LoginPage(),
},
),
),
);
}
}
而在attemptLogIn
方法中,你只需要发送一个通知:
Future<void> attemptLogIn(
String username, String password, BuildContext context) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (kDebugMode) print("$username $password");
final http.Response res = await http.post(
"..............the route.............",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{"email": username, "password": password}),
);
if (res.statusCode == 200) {
// check if the login is valid first
//...
prefs.setString('jwt', res.body);
var value = prefs.getString('jwt');
Map<String, dynamic> valueMap = jsonDecode(value);
TokenClass token = TokenClass.fromJson(valueMap);
// send notification to a LoginNotification Listener
LoginNotification(token).dispatch(context);
Navigator.of(context).pushNamed('/home');
} else {
return _showMyDialoglogin(context, res.statusCode);
}
}
如您所见,使用 InheretedWidget
并不是那么容易,所有这些都是针对单个值。
也许考虑其他状态管理解决方案,我没有任何特别的建议,但 flutter 文档有一个最常用的列表 here。
这是我正在制作的应用程序的登录代码。我想更新 parent_inherit(Inherited Widget) 中的令牌,这是我在发布 request.But 后得到的 我无法理解如何在没有该构建方法的情况下显式更新 Inherited widget 变量的值或 parent_inherit widget.I 想要更改 Inherited widget(parent_inherit) 中的标记值。
Future<void> attemptLogIn(String username, String password,BuildContext context) async {
String parentToken= parent_inherit.of(context);
SharedPreferences prefs = await SharedPreferences.getInstance();
print("$username $password");
final http.Response res = await http.post(
"..............the route.............",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
"email": username,
"password": password
}),
);
if(res.statusCode == 200) {
prefs.setString('jwt',res.body);
var value=prefs.getString('jwt');
Map<String,dynamic> valueMap=jsonDecode(value);
TokenClass token=TokenClass.fromJson(valueMap);
parentToken=token.token;// I was trying something like this,but it seems to not work
Navigator.of(context).pushNamed('/home');
}
else{
return _showMyDialoglogin(context,res.statusCode);
}
}
此外,在上面的文件中,当我在上面声明 parentToken 并向下使用它时,它仍然显示上面声明的 parentToken 不是 used.It 当我将鼠标悬停在 it.Why 上时也会显示警告,所以?
parent_inherit.dart
class parent_inherit extends InheritedWidget {
final String token;
const parent_inherit({
Key key,
@required this.token,
Widget child})
:super(key:key,child: child);
@override
bool updateShouldNotify(parent_inherit oldWidget) =>true;
static String of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<parent_inherit>().token;
}
TokenClass.dart
class TokenClass{
final String token;
TokenClass(this.token);
TokenClass.fromJson(Map<String,dynamic> json)
: token=json['token'];
}
我的主要功能 - 在主要功能中,令牌值存在问题,它无法正确更新和获取继承内部和外部的值 widget.Sometimes 它也使用以前的令牌值。
main.dart
bool checkingKey;
String tokenName;
TokenClass token;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Paint.enableDithering = true;
const defaultJson = '{}';
var prefs = await SharedPreferences.getInstance();
checkingKey = prefs.containsKey("jwt");
tokenName=prefs.getString('jwt');
Map<String, dynamic> valueMap = jsonDecode(tokenName??defaultJson);
token=TokenClass.fromJson(valueMap);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return parent_inherit(
token: checkingKey==false?'':token.token,
child: MaterialApp(
home: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
color: Color(0xffccffcc),
child: !checkingKey ? LoginPage() : mainPage(),
),
),
),
routes: <String,WidgetBuilder>{
'/home':(BuildContext context) => mainPage(),
'/login':(BuildContext context) => LoginPage(),
},
),
);
}
}
也欢迎其他建议...
更新 InheritedWidget
的一种方法是使用 Notification
。
首先,我们有通知Class:
class LoginNotification extends Notification {
final TokenClass token;
LoginNotification(this.token);
}
然后我们用通知侦听器包装 parent_inherit
:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return NotificationListener<LoginNotification>(
onNotification: (loginNotification) {
setState(() {
token = loginNotification.token;
checkingKey = true;
});
return true;
},
child: parent_inherit(
token: checkingKey ? token.token : '',
child: MaterialApp(
home: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
color: Color(0xffccffcc),
child: checkingKey ? MainPage() : LoginPage(),
),
),
),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => MainPage(),
'/login': (BuildContext context) => LoginPage(),
},
),
),
);
}
}
而在attemptLogIn
方法中,你只需要发送一个通知:
Future<void> attemptLogIn(
String username, String password, BuildContext context) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (kDebugMode) print("$username $password");
final http.Response res = await http.post(
"..............the route.............",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{"email": username, "password": password}),
);
if (res.statusCode == 200) {
// check if the login is valid first
//...
prefs.setString('jwt', res.body);
var value = prefs.getString('jwt');
Map<String, dynamic> valueMap = jsonDecode(value);
TokenClass token = TokenClass.fromJson(valueMap);
// send notification to a LoginNotification Listener
LoginNotification(token).dispatch(context);
Navigator.of(context).pushNamed('/home');
} else {
return _showMyDialoglogin(context, res.statusCode);
}
}
如您所见,使用 InheretedWidget
并不是那么容易,所有这些都是针对单个值。
也许考虑其他状态管理解决方案,我没有任何特别的建议,但 flutter 文档有一个最常用的列表 here。