Flutter:使用共享首选项时对 null 的方法调用
Flutter : method call on null when using shared preference
我想使用共享首选项来保持用户登录,我正在使用 api 和提供者。
我试图将它放在主页面中,但我不知道该怎么做,因为我有两个不同的页面,所以我在第一页中使用了它,但我发现了另一个错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception:
NoSuchMethodError: The method 'login' was called on null. E/flutter (
4199): Receiver: null
这是我使用的方法
UserProvider userProvider;
ServiceProvider serviceProvider;
bool alive = true;
bool isLoading = false;
var page;
@override
initState() {
init();
super.initState();
}
init() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool language = prefs.getBool('language');
bool type = prefs.getBool('type');
bool login = prefs.getBool('islog');
if (alive) {
if (language == true && type == true && login == true) {
signIn();
} else if ((language == true && type == false && login == true)) {
visitor();
}
} else {
if (alive) {
setState(() {
isLoading = false;
});
}
}
}
signIn() async {
//var res = await userProvider.residentLogin(context, phone, pass);
SharedPreferences prefs = await SharedPreferences.getInstance();
var phone = prefs.getString('phone');
String pass = prefs.getString("pass");
bool type = prefs.getBool('type');
print("Shared ***************resident********************************");
await userProvider.residentLogin(context, phone, pass);
await serviceProvider.getHomeServiceList(context);
await serviceProvider.getAdsList(context);
await serviceProvider.getVideosList(context);
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => ResidentBottomTab()));
print('Hello Tourist !!');
}
visitor() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var phone = prefs.getString('phone');
String pass = prefs.getString("pass");
await userProvider.login(context, phone, pass);
await serviceProvider.getVisitorAdsList(context);
await serviceProvider.getVisitorVideosList(context);
bool type = prefs.getBool('type');
print("Shared ******************visitor*****************************");
if (alive) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => VisitorHome()));
print('Hello Tourist !!');
}
}
@override
void dispose() {
alive = false;
super.dispose();
}
登录方式
Future<VisitorLoginModel> login(BuildContext context, phone, pass) async {
final Map<String, dynamic> body = {
'phone': phone,
'password': pass,
'token': '123',
'serial_number': '123',
'lang': 'en',
'os': 'android',
};
_isLoading = true;
notifyListeners();
print('Starting request');
http.Response response = await http.post(Environment.userLogin,
body: json.encode(body), headers: Environment.requestHeader);
print('Completed request');
print('user SignUp response : ${response.body}');
//print(body.toString());
Map<String, dynamic> res = json.decode(response.body);
var results;
if (res['status'] == 1) {
// login successful
_visitorLoginModel = parseVisitorLogin(response.body);
Provider.of<LoginVisitorUserProvider>(context, listen: false).userData =
visitorLoginModel;
Provider.of<LoginVisitorUserProvider>(context, listen: false)
.sessionToken = visitorLoginModel.data.token;
headers = Provider.of<LoginVisitorUserProvider>(context, listen: false)
.httpHeader;
// print('token');
print('this is session token' +
Provider.of<LoginVisitorUserProvider>(context, listen: false)
.sessionToken);
} else {
// login failed;
results =
FailedRequest(code: 401, message: res['massage'], status: false);
}
_isLoading = false;
notifyListeners();
return visitorLoginModel;
}
所以任何人都有解决这个问题的想法!
正在对未初始化的变量进行方法调用 await userProvider.login(context, phone, pass);
。 UserProvider userProvider;
已声明但未初始化
这里的问题是 userProvider
正在声明但未初始化,serviceProvider
也是如此
在 Flutter 中,任何未初始化的变量都将隐式分配 null
因此,在 await userProvider.login(context, phone, pass);
行调用 login
方法,其中 userProvider 不仅被初始化
要解决此问题,请执行以下操作,
在初始状态,
userProvider = Provider.of<UserProvider>(context, listen: false);
我想使用共享首选项来保持用户登录,我正在使用 api 和提供者。 我试图将它放在主页面中,但我不知道该怎么做,因为我有两个不同的页面,所以我在第一页中使用了它,但我发现了另一个错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'login' was called on null. E/flutter ( 4199): Receiver: null
这是我使用的方法
UserProvider userProvider;
ServiceProvider serviceProvider;
bool alive = true;
bool isLoading = false;
var page;
@override
initState() {
init();
super.initState();
}
init() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool language = prefs.getBool('language');
bool type = prefs.getBool('type');
bool login = prefs.getBool('islog');
if (alive) {
if (language == true && type == true && login == true) {
signIn();
} else if ((language == true && type == false && login == true)) {
visitor();
}
} else {
if (alive) {
setState(() {
isLoading = false;
});
}
}
}
signIn() async {
//var res = await userProvider.residentLogin(context, phone, pass);
SharedPreferences prefs = await SharedPreferences.getInstance();
var phone = prefs.getString('phone');
String pass = prefs.getString("pass");
bool type = prefs.getBool('type');
print("Shared ***************resident********************************");
await userProvider.residentLogin(context, phone, pass);
await serviceProvider.getHomeServiceList(context);
await serviceProvider.getAdsList(context);
await serviceProvider.getVideosList(context);
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => ResidentBottomTab()));
print('Hello Tourist !!');
}
visitor() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var phone = prefs.getString('phone');
String pass = prefs.getString("pass");
await userProvider.login(context, phone, pass);
await serviceProvider.getVisitorAdsList(context);
await serviceProvider.getVisitorVideosList(context);
bool type = prefs.getBool('type');
print("Shared ******************visitor*****************************");
if (alive) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => VisitorHome()));
print('Hello Tourist !!');
}
}
@override
void dispose() {
alive = false;
super.dispose();
}
登录方式
Future<VisitorLoginModel> login(BuildContext context, phone, pass) async {
final Map<String, dynamic> body = {
'phone': phone,
'password': pass,
'token': '123',
'serial_number': '123',
'lang': 'en',
'os': 'android',
};
_isLoading = true;
notifyListeners();
print('Starting request');
http.Response response = await http.post(Environment.userLogin,
body: json.encode(body), headers: Environment.requestHeader);
print('Completed request');
print('user SignUp response : ${response.body}');
//print(body.toString());
Map<String, dynamic> res = json.decode(response.body);
var results;
if (res['status'] == 1) {
// login successful
_visitorLoginModel = parseVisitorLogin(response.body);
Provider.of<LoginVisitorUserProvider>(context, listen: false).userData =
visitorLoginModel;
Provider.of<LoginVisitorUserProvider>(context, listen: false)
.sessionToken = visitorLoginModel.data.token;
headers = Provider.of<LoginVisitorUserProvider>(context, listen: false)
.httpHeader;
// print('token');
print('this is session token' +
Provider.of<LoginVisitorUserProvider>(context, listen: false)
.sessionToken);
} else {
// login failed;
results =
FailedRequest(code: 401, message: res['massage'], status: false);
}
_isLoading = false;
notifyListeners();
return visitorLoginModel;
}
所以任何人都有解决这个问题的想法!
正在对未初始化的变量进行方法调用 await userProvider.login(context, phone, pass);
。 UserProvider userProvider;
已声明但未初始化
这里的问题是 userProvider
正在声明但未初始化,serviceProvider
在 Flutter 中,任何未初始化的变量都将隐式分配 null
因此,在 await userProvider.login(context, phone, pass);
行调用 login
方法,其中 userProvider 不仅被初始化
要解决此问题,请执行以下操作, 在初始状态,
userProvider = Provider.of<UserProvider>(context, listen: false);