簡體   English   中英

更新繼承小部件的變量值

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM