颤振与 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();
【问题讨论】:
checkUserType
是 async
,它应该是 Future<void>
而不是 void
,你必须等待 checkUserType
完成,所以你必须在里面调用它而不是 WidgetsBinding.instance.addPostFrameCallback((_) async => await checkUserType());
因为initState
不是async
函数
这里的答案link,与调用setState
inside initState
有关,可以提供帮助
@ikerfah 尝试在 init() 中添加 Future<void>
和 WidgetsBinding.instance.addPostFrameCallback((_) async => 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 共享首选项问题的主要内容,如果未能解决你的问题,请参考以下文章