[英]Update value of variable of inherited widget
這是我正在制作的應用程序的登錄代碼。 我想更新在發布請求后獲得的 parent_inherit(Inherited Widget) 中的令牌。但是我無法理解如何在沒有該構建方法或 parent_inherit 小部件的情況下顯式更新 Inherited 小部件變量的值。我想改變繼承小部件(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 沒有被使用。它還顯示當我 hover 超過它時的警告。為什么會這樣?
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'];
}
我的主要 function - 在主要 function 中,令牌值存在問題,它無法正確更新和獲取繼承小部件內部和外部的值。有時它也使用以前的令牌值。
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
並不容易,所有這些都是針對單個值的。
也許考慮其他 state 管理解決方案,我沒有任何特別的建議,但 flutter 文檔在此處列出了最常用的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.