【问题标题】:Update value of variable of inherited widget更新继承小部件的变量值
【发布时间】:2021-05-13 09:30:00
【问题描述】:

这是我正在制作的应用程序的登录代码。我想更新在发布请求后获得的 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 没有被使用。当我将鼠标悬停在它上面时它也会显示警告。为什么会这样?

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'];

}

我的主函数 - 在主函数中,令牌值存在问题,它无法正确更新和获取继承小部件内部和外部的值。有时它也使用以前的令牌值。

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(),
        },
      ),
    );
  }
}

也欢迎其他建议...

【问题讨论】:

    标签: flutter authentication jwt inherited-widget


    【解决方案1】:

    更新InheritedWidget 的一种方法是使用Notification。

    首先,我们有我们的通知类:

    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 并不容易,所有这些都是针对单个值的。

    也许考虑其他状态管理解决方案,我没有任何特别的建议,但颤振文档有一个最常用的列表here。

    【讨论】:

    • 谢谢!它起作用了,我想知道我什么时候创建了一个返回类型小部件的函数,作为回报,我输入了“parent_inherit(token:tokenCorrector);”在tokenCorrector中我将新的令牌值作为输入,那么为什么它当时没有工作.我们不能像那样更新继承的小部件值吗?这就像一个子小部件更新了值并且父级不能接受它。
    猜你喜欢
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 2023-01-04
    • 2021-05-24
    相关资源
    最近更新 更多