颤振与 setInt 共享首选项问题

Posted

技术标签:

【中文标题】颤振与 setInt 共享首选项问题【英文标题】:Flutter shared preferences issue with setInt 【发布时间】:2020-11-08 20:01:53 【问题描述】:

我正在尝试构建一个由学生老师和家长三个角色组成的应用程序。我想过使用身份验证更改流和共享首选项来实现身份验证。即 setInt('usertype',1) 代表学生,2 代表老师,3 代表家长。

这是我的学生注册屏幕,如果用户注册成功,我将用户类型设置为 1,我也为老师和家长注册屏幕做了同样的操作。

class StudentRegisterScreen extends StatefulWidget 
  final Function toggleView;
  StudentRegisterScreen(this.toggleView);
  @override
  _StudentRegisterScreenState createState() => _StudentRegisterScreenState();


class _StudentRegisterScreenState extends State<StudentRegisterScreen> 
  final AuthService _authService = AuthService();

  final _formkey = GlobalKey<FormState>();
  final usertype = await SharedPreferences.getInstance();
  //String name = '';
  //String email = '';
  //String password = '';
  
  @override
  Widget build(BuildContext context) 
    //String _message = '';
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      backgroundColor: HexColor(studentPrimaryColour),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Form(
            key: _formkey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SizedBox(
                  height: 20.0,
                ),
                HeadingText(
                  text: 'Register',
                  size: 60.0,
                  color: Colors.white,
                ),
                Container(
                  height: 20.0,
                  child: HeadingText(
                    text: AuthService().message,
                    size: 20.0,
                    color: Colors.white,
                  ),
                ),
                SizedBox(
                  height: 25.0,
                ),
                RoundedInputField(
                  hintText: 'Name',
                  validator: (val) =>
                      val.isEmpty ? 'Oops! you left this field empty' : null,
                  onChanged: (val) 
                    name = val;
                  ,
                ),
                SizedBox(
                  height: 5.0,
                ),
               
                RoundedInputField(
                  hintText: 'Email',
                  validator: (val) => val.isEmpty ? 'enter an email' : null,
                  onChanged: (val) 
                    email = val;
                  ,
                ),
                SizedBox(
                  height: 5.0,
                ),
                RoundedInputField(
                    hintText: 'Password',
                    validator: (val) =>
                        val.isEmpty ? 'atleast provide a password' : null,
                    boolean: true,
                    onChanged: (val) 
                      password = val;
                    ),
                SizedBox(
                  height: 5.0,
                ),
                Container(
                  margin: EdgeInsets.symmetric(vertical: 10),
                  width: size.width * 0.8,
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(29),
                    child: FlatButton(
                      padding:
                          EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                      color: Colors.white,
                      onPressed: () async 
                        
                        // 
                        //   if (_formkey.currentState.validate()) 
                        //     print(email);
                        //     print(password);
                               usertype.setInt('usertype',1);
                        //     dynamic result =
                        //         await _authService.registerWithEmailpasswd(
                        //             email,
                        //             password,
                        //             name,
                        //            );
                        //    
                      ,
                      child: HeadingText(
                        color: HexColor(studentPrimaryColour),
                        text: 'Register',
                        size: 12.0,
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 15.0,
                ),
                InkWell(
                  onTap: () 
                    // Navigator.pop(context);
                    widget.toggleView();
                  ,
                  child: HeadingText(
                    text: 'Already registered?',
                    color: Colors.white,
                    size: 10,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  



但我遇到了错误

I/flutter (13157): 0
E/flutter (13157): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'setInt' was called on null.
E/flutter (13157): Receiver: null
E/flutter (13157): Tried calling: setInt("usertype", 1)


下面是我现在的包装类,我想在继续之前将值打印到控制台上,我将实现切换案例以显示不同的用户屏幕


class Welcomescreen extends StatefulWidget 
  @override
  _WelcomescreenState createState() => _WelcomescreenState();


class _WelcomescreenState extends State<Welcomescreen> 
  SharedPreferences userDetails;
  int usertype;
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    checkUserType();
  

  void checkUserType() async 
    userDetails = await SharedPreferences.getInstance();
    setState(() 
      usertype = userDetails.getInt('usertype') ?? 0;
    );

    print(usertype);
  

  @override
  Widget build(BuildContext context) 
    //final user = Provider.of<UserModel>(context);
    return Body();
  



【问题讨论】:

checkUserTypeasync ,它应该是 Future&lt;void&gt; 而不是 void,你必须等待 checkUserType 完成,所以你必须在里面调用它而不是 WidgetsBinding.instance.addPostFrameCallback((_) async =&gt; await checkUserType());因为initState 不是async 函数 这里的答案link,与调用setStateinside initState有关,可以提供帮助 @ikerfah 尝试在 init() 中添加 Future&lt;void&gt;WidgetsBinding.instance.addPostFrameCallback((_) async =&gt; await checkUserType()); ,但抛出相同的错误.. ``` E/flutter (14753): [ERROR:flutter/lib/ui/ ui_dart_state.cc(177)] 未处理的异常:NoSuchMethodError:在 null 上调用了方法“setInt”。 E/flutter(14753):接收者:null E/flutter(14753):尝试调用:setInt("usertype", 1)``` 【参考方案1】:

userType 引用了一个未来值SharedPreference.getInstance(),通过创建final userType = await SharedPrefence.getInstance(),您告诉代码调用 userType 将返回 SharedPrefence.getInstance() 的 Future,在您真正等待之前不会解析为 SharedPreference 类它(使用 await 没有做任何事情,因为您实际上并没有在 async 函数中)

试着这样称呼它:

onPressed: () async 
    (await usertype).setInt('usertype',1);
     // or maybe (userType).setInt('usertype',1);

userType 将被替换为您引用的值 (await SharedPreference.getInstance())

程序看起来像这样:

onPressed: () async 
    (await SharedPreference.getInstance()).setInt('usertype',1);

首先它需要等待future,然后你才能真正调用它的方法

【讨论】:

以上是关于颤振与 setInt 共享首选项问题的主要内容,如果未能解决你的问题,请参考以下文章

Flutter ios 共享首选项显示 setstring on null 错误

根据存储在共享首选项中的记住我状态导航到屏幕

在共享首选项中获取文件大小

Firestore 查询变量以填充共享首选项

添加值后增加共享首选项键

如何以共享首选项保存图像?