在Future fetchStudentInfo()函数中,我想使用Auth类中的userId进行过滤。 userId嵌入在URL中,它将从数据库中检索数据。但是,问题在于功能本身缺少上下文。但是,我找不到在上下文中传递内容的方法。如果有任何传说可以帮助我,那将是很棒的。在flutter文档中可以找到从Internet检索数据的解决方案。而且我不想硬编码userId。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import '../model/student.dart';
import '../provider/auth.dart';
Future<Student> fetchStudentInfo() async {
final auth = Provider.of<Auth>(context);
final response = await http.post(
'https://intermediary-sharpe.000webhostapp.com/Student/read_one.php?userId=$auth.userId');
if (response.statusCode == 200) {
return Student.fromJson(json.decode(response.body));
} else {
throw Exception('Failed');
}
}
class ProfileScreen extends StatefulWidget {
@override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
Future<Student> student;
@override
void initState() {
// TODO: implement initState
super.initState();
student = fetchStudentInfo();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<Student>(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.studentId);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return CircularProgressIndicator();
},
future: student,
),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
import '../model/http_exception.dart';
class Auth with ChangeNotifier {
String _token;
DateTime _expiryDate;
String userId;
Timer _authTimer;
bool get isAuthenticated {
return token != null;
}
String get token {
if (_expiryDate != null &&
_expiryDate.isAfter(DateTime.now()) &&
_token != null) {
return _token;
}
return null;
}
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final url =
'https://identitytoolkit.googleapis.com/v1/accounts:$urlSegment?key=AIzaSyCkNZysDY4PGpScw2jUlBpd0mvpGjgSEag';
try {
final response = await http.post(
url,
body: json.encode(
{
'email': email,
'password': password,
'returnSecureToken': true,
},
),
);
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
}
_token = responseData['idToken'];
userId = responseData['localId'];
_expiryDate = DateTime.now().add(
Duration(
seconds: int.parse(
responseData['expiresIn'],
),
),
);
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode({
'token': _token,
'userId': userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
//Auto Login Function
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('userData')) {
return false;
}
final extractedUserData =
json.decode(prefs.getString('userData')) as Map<String, Object>;
final expiryDate = DateTime.parse(extractedUserData['expiryDate']);
if (expiryDate.isBefore(DateTime.now())) {
return false;
}
_token = extractedUserData['token'];
userId = extractedUserData['userId'];
_expiryDate = expiryDate;
notifyListeners();
_autoLogout();
return true;
}
//SignUp function
Future<void> signUp(String email, String password) async {
return _authenticate(email, password, 'signUp');
}
//Login Function
Future<void> login(String email, String password) async {
return _authenticate(email, password, 'signInWithPassword');
}
//Logout Function
Future<void> logout() async {
_token = null;
userId = null;
_expiryDate = null;
if (_authTimer != null) {
_authTimer.cancel();
_authTimer = null;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
prefs.clear();
}
//Auto Logout function
void _autoLogout() {
if (_authTimer != null) {
_authTimer.cancel();
}
final timeToExpiry = _expiryDate.difference(DateTime.now()).inSeconds;
_authTimer = Timer(Duration(seconds: timeToExpiry), logout);
}
//PHP related functions
}
谢谢。
答案 0 :(得分:0)
最简单的解决方案不是将上下文传递到fetchStudentInfo
吗?
您将fetchStudentInfo()
更改为fetchStudentInfo(BuildContext context)
。然后,当您调用该方法时,将在所需的上下文中传递。这样,您就可以使用适当的上下文。
答案 1 :(得分:0)
我同意@lyio,您需要修改函数以传递上下文,但是传递上下文之后,您不能按照documentation of initState所述从initState调用它
BuildContext.dependOnInheritedWidgetOfExactType
从这种方法。但是,didChangeDependencies
将在此方法之后立即调用,并且BuildContext.dependOnInheritedWidgetOfExactType
可以在此处使用。
在后台使用Provider.of(context)获取提供者正在使用继承的小部件,因此不能使用initState中的上下文调用
因此使用didChangeDependencies而不是initState来实现您的fetchStudentsInfo(context)
方法
答案 2 :(得分:0)
如果您不在状态类之外使用fetchStudentInfo()
,则只需将该方法移到状态类中即可解决问题。
因为任何状态类都有默认定义的context
getter。