Flutter 如何获取提供程序工作的上下文?颤振
在将来的fetchStudentInfo()函数中,我希望使用Auth类中的userId进行过滤。用户ID嵌入在URL中,它将从数据库检索数据。但是,问题是功能本身缺乏上下文。然而,我想不出在上下文中传递的方法。如果有传奇人物能帮助我那就太好了。从internet检索数据的解决方案可在颤振文档中找到。我不想硬编码用户IDFlutter 如何获取提供程序工作的上下文?颤振,flutter,state,provider,Flutter,State,Provider,在将来的fetchStudentInfo()函数中,我希望使用Auth类中的userId进行过滤。用户ID嵌入在URL中,它将从数据库检索数据。但是,问题是功能本身缺乏上下文。然而,我想不出在上下文中传递的方法。如果有传奇人物能帮助我那就太好了。从internet检索数据的解决方案可在颤振文档中找到。我不想硬编码用户ID import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http
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,
),
);
}
}
导入'dart:convert';
进口“包装:颤振/材料.省道”;
将“package:http/http.dart”导入为http;
导入“包:provider/provider.dart”;
导入“../model/student.dart”;
导入“../provider/auth.dart”;
Future fetchStudentInfo()异步{
最终认证=提供者(上下文);
最终响应=等待http.post(
'https://intermediary-sharpe.000webhostapp.com/Student/read_one.php?userId=$auth.userId');
如果(response.statusCode==200){
返回Student.fromJson(json.decode(response.body));
}否则{
抛出异常('Failed');
}
}
类ProfileScreen扩展StatefulWidget{
@凌驾
_ProfileScreenState createState()=>\u ProfileScreenState();
}
类_ProfileScreenState扩展状态{
未来学生;
@凌驾
void initState(){
//TODO:实现initState
super.initState();
student=fetchStudentInfo();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:未来建设者(
生成器:(上下文,快照){
if(snapshot.hasData){
返回文本(snapshot.data.studentId);
}else if(snapshot.hasrerror){
返回文本(“${snapshot.error}”);
}
返回循环ProgressIndicator();
},
未来:学生,
),
);
}
}
import'包装:flift/cupertino.dart';
将“package:http/http.dart”导入为http;
导入“dart:convert”;
导入“dart:async”;
导入“package:shared_preferences/shared_preferences.dart”;
导入“../model/http_exception.dart”;
使用ChangeNotifier类身份验证{
字符串标记;
日期时间_expiryDate;
字符串用户标识;
定时器;
布尔得到了认证{
返回令牌!=null;
}
字符串获取令牌{
如果(_expiryDate!=null&&
_expireydate.isAfter(DateTime.now())&&
_令牌!=null){
返回令牌;
}
返回null;
}
未来(
字符串电子邮件、字符串密码、字符串URL(段)异步{
最终url=
'https://identitytoolkit.googleapis.com/v1/accounts:$URLSEMENT?key=AIzaSyCkNZysDY4PGpScw2jUlBpd0mvpGjgSEag';
试一试{
最终响应=等待http.post(
网址,
正文:json.encode(
{
“电子邮件”:电子邮件,
“密码”:密码,
“returnSecureToken”:true,
},
),
);
final responseData=json.decode(response.body);
if(responseData['error']!=null){
抛出HttpException(responseData['error']['message']);
}
_令牌=响应数据['idToken'];
userId=responseData['localId'];
_expireydate=DateTime.now().add(
持续时间(
秒:int.parse(
响应数据['expiresIn'],
),
),
);
_自体();
notifyListeners();
final prefs=wait SharedPreferences.getInstance();
final userData=json.encode({
“令牌”:,
“userId”:userId,
'expiryDate':_expiryDate.toIso8601String(),
});
prefs.setString('userData',userData);
}捕获(错误){
投掷误差;
}
}
//自动登录功能
Future tryAutoLogin()异步{
final prefs=wait SharedPreferences.getInstance();
如果(!prefs.containsKey('userData')){
返回false;
}
最终提取的数据=
json.decode(prefs.getString('userData'))作为映射;
final expireydate=DateTime.parse(extractedUserData['expireydate']);
if(expireydate.isBefore(DateTime.now()){
返回false;
}
_token=extractedUserData['token'];
userId=extractedUserData['userId'];
_expiryDate=expiryDate;
notifyListeners();
_自体();
返回true;
}
//注册函数
未来注册(字符串电子邮件、字符串密码)异步{
返回“身份验证”(电子邮件、密码、“注册”);
}
//登录功能
未来登录(字符串电子邮件、字符串密码)异步{
返回“验证(电子邮件、密码、“使用密码登录”);
}
//注销功能
将来注销()异步{
_令牌=null;
userId=null;
_expireydate=null;
如果(_authTimer!=null){
_authTimer.cancel();
_authTimer=null;
}
notifyListeners();
final prefs=wait SharedPreferences.getInstance();
prefs.clear();
}
//自动注销功能
void_autologue(){
如果(_authTimer!=null){
_authTimer.cancel();
}
final timeToExpiry=\u expiryDate.difference(DateTime.now()).insionds;
_authTimer=计时器(持续时间(秒:timeToExpiry),注销);
}
//PHP相关函数
}
提前谢谢。最简单的解决方案不是将上下文传递到
fetchStudentInfo
您可以将fetchStudentInfo()
更改为fetchStudentInfo(构建上下文)
。然后,当调用在所需上下文中传递的方法时。这样,您就可以使用适当的上下文。我同意,您需要修改函数以传递上下文,但是在传递上下文后,您不能按照中的说明从initState调用它
BuildContext.dependonheritedwidgetofexacttype
来自此方法。但是,此方法之后将立即调用didChangeDependencies
,并且可以在那里使用BuildContext.dependOnInheritedWidgetOfExactType
在引擎盖下使用provider.of(context)获取provider是使用继承的小部件,因此不能使用
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
}