如何在 riverpod 中调用 http.post?
How to make http.post call in riverpod?
我正在尝试进行 post 调用,将表单数据发送到 API 并获得响应。
我想打一个网络post-call,发送手机号、密码,并从user_repo获取用户数据,并将其存储在将来访问的状态。
我不确定如何添加用户状态提供程序并在按下按钮时调用它。
例如:
我的 AuthScreen:这是实施 Ui 的地方。
class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
TextEditingController _phoneController;
TextEditingController _passwordController;
bool _isHidden = true;
void _togglePasswordView() {
setState(() {
_isHidden = !_isHidden;
});
}
@override
void initState() {
super.initState();
_phoneController = TextEditingController();
_passwordController = TextEditingController();
}
@override
void dispose() {
_phoneController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.w500,
),
),
TextField(
keyboardType: TextInputType.phone,
controller: _phoneController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_android),
hintText: 'Enter your registered mobile number'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
hintText: 'Enter your password',
suffixIcon: InkWell(
child: Icon(
_isHidden ? Icons.visibility_off : Icons.visibility),
onTap: _togglePasswordView,
),
),
obscureText: _isHidden,
),
RaisedButton(
onPressed: ()=>{},
child: Text("login"),
),
],
),
),
);
}
我应该为 onPressed 写什么? context.read(用户状态)??
用户模式:
class UserData {
UserData({
this.id,
this.name,
this.mobile,
this.email,
this.image,
});
String id;
String name;
String mobile;
String email;
String image;
factory UserData.fromJson(Map<String, dynamic> json) => UserData(
id: json["id"],
name: json["name"],
mobile: json["mobile"],
email: json["email"],
image: json["image"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"mobile": mobile,
"email": email,
"image": image,
};
}
用户回购:
class UserRepository {
Future<dynamic> fetchUser(String mobile, String password) async {
var body = {"mobile": mobile, "password": password};
final response = await _implementation.post(my_url, body: body);
return response;
}
}
州:
final userState = FutureProvider<dynamic>((ref) async {
UserRepository().fetchUser(mobile, password);
// How to make this work??
});
编辑:
Tayormi 提供的解决方案完美运行。
我添加了一些代码来存储用户在需要时访问。
在状态提供程序下创建以存储用户:
final userData = StateProvider<UserData>((ref) => null);
将 userProvider 修改为:
final userProvider = StateNotifierProvider<UserController>((ref) {
final user = ref.read(userData);
return UserController(user);
});
在 userController 的 try 块中,我们可以按如下方式更新 userData:
class UserController extends StateNotifier<FetchUserState> {
final userData;
UserController(this.userData) : super(UserFetchInitial());
void fetchUser(String mobile, String password) async {
final userRepo = UserRepository();
state = UserFetching();
try {
final response = await userRepo.fetchUser(mobile, password);
if (response.id != null) {
userData.state = response;
state = UserFetched();
} else {
state = UserFetchError();
}
} catch (error) {
print(error);
state = UserFetchError();
}
}
}
感谢@Tayormi 帮助我找到解决方案..
您应该使用状态通知程序提供程序,因为您已经有一个存储库来处理您的 API 调用。
首先,您可以为提供者创建一个状态,如下所示(我使用的是 Equatable 包):
abstract class FetchUserState extends Equatable {
FetchUserState();
}
class UserFetchInitial extends FetchUserState {
UserFetchInitial();
@override
List<Object> get props => [];
}
class UserFetched extends FetchUserState {
UserFetched();
@override
List<Object> get props => [];
}
class UserFetching extends FetchUserState {
UserFetching();
@override
List<Object> get props => [];
}
class UserFetchError extends FetchUserState {
UserFetchError();
@override
List<Object> get props => [];
}
接下来,我们创建一个StateNotifierProvider
final userProvider =
StateNotifierProvider<UserController>((ref) => UserController());
接下来我们创建扩展状态的用户控制器
class UserController extends StateNotifier<FetchUserState> {
UserController() :
super(UserFetchInitial());
void fetchUser(String mobile, String password) async {
final userRepository = UserRepository();
state = UserFetching();
try {
final res = await userRepository.fetchUser(mobile, password);
if (res) {
state = UserFetched();
} else {
state = UserFetchError();
}
} catch (e) {
state = UserFetchError();
}
}
}
最后,在 UI 上的 onPressed 中,
您可以轻松做到:
context.read(userProvider).fetchUser(_phoneController.text.trim(),
_passwordController.text);
让我知道这是否适合你。
我正在尝试进行 post 调用,将表单数据发送到 API 并获得响应。
我想打一个网络post-call,发送手机号、密码,并从user_repo获取用户数据,并将其存储在将来访问的状态。
我不确定如何添加用户状态提供程序并在按下按钮时调用它。
例如:
我的 AuthScreen:这是实施 Ui 的地方。
class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
TextEditingController _phoneController;
TextEditingController _passwordController;
bool _isHidden = true;
void _togglePasswordView() {
setState(() {
_isHidden = !_isHidden;
});
}
@override
void initState() {
super.initState();
_phoneController = TextEditingController();
_passwordController = TextEditingController();
}
@override
void dispose() {
_phoneController.dispose();
_passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.w500,
),
),
TextField(
keyboardType: TextInputType.phone,
controller: _phoneController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_android),
hintText: 'Enter your registered mobile number'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
hintText: 'Enter your password',
suffixIcon: InkWell(
child: Icon(
_isHidden ? Icons.visibility_off : Icons.visibility),
onTap: _togglePasswordView,
),
),
obscureText: _isHidden,
),
RaisedButton(
onPressed: ()=>{},
child: Text("login"),
),
],
),
),
);
}
我应该为 onPressed 写什么? context.read(用户状态)??
用户模式:
class UserData {
UserData({
this.id,
this.name,
this.mobile,
this.email,
this.image,
});
String id;
String name;
String mobile;
String email;
String image;
factory UserData.fromJson(Map<String, dynamic> json) => UserData(
id: json["id"],
name: json["name"],
mobile: json["mobile"],
email: json["email"],
image: json["image"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"mobile": mobile,
"email": email,
"image": image,
};
}
用户回购:
class UserRepository {
Future<dynamic> fetchUser(String mobile, String password) async {
var body = {"mobile": mobile, "password": password};
final response = await _implementation.post(my_url, body: body);
return response;
}
}
州:
final userState = FutureProvider<dynamic>((ref) async {
UserRepository().fetchUser(mobile, password);
// How to make this work??
});
编辑: Tayormi 提供的解决方案完美运行。
我添加了一些代码来存储用户在需要时访问。
在状态提供程序下创建以存储用户:
final userData = StateProvider<UserData>((ref) => null);
将 userProvider 修改为:
final userProvider = StateNotifierProvider<UserController>((ref) {
final user = ref.read(userData);
return UserController(user);
});
在 userController 的 try 块中,我们可以按如下方式更新 userData:
class UserController extends StateNotifier<FetchUserState> {
final userData;
UserController(this.userData) : super(UserFetchInitial());
void fetchUser(String mobile, String password) async {
final userRepo = UserRepository();
state = UserFetching();
try {
final response = await userRepo.fetchUser(mobile, password);
if (response.id != null) {
userData.state = response;
state = UserFetched();
} else {
state = UserFetchError();
}
} catch (error) {
print(error);
state = UserFetchError();
}
}
}
感谢@Tayormi 帮助我找到解决方案..
您应该使用状态通知程序提供程序,因为您已经有一个存储库来处理您的 API 调用。 首先,您可以为提供者创建一个状态,如下所示(我使用的是 Equatable 包):
abstract class FetchUserState extends Equatable {
FetchUserState();
}
class UserFetchInitial extends FetchUserState {
UserFetchInitial();
@override
List<Object> get props => [];
}
class UserFetched extends FetchUserState {
UserFetched();
@override
List<Object> get props => [];
}
class UserFetching extends FetchUserState {
UserFetching();
@override
List<Object> get props => [];
}
class UserFetchError extends FetchUserState {
UserFetchError();
@override
List<Object> get props => [];
}
接下来,我们创建一个StateNotifierProvider
final userProvider =
StateNotifierProvider<UserController>((ref) => UserController());
接下来我们创建扩展状态的用户控制器
class UserController extends StateNotifier<FetchUserState> {
UserController() :
super(UserFetchInitial());
void fetchUser(String mobile, String password) async {
final userRepository = UserRepository();
state = UserFetching();
try {
final res = await userRepository.fetchUser(mobile, password);
if (res) {
state = UserFetched();
} else {
state = UserFetchError();
}
} catch (e) {
state = UserFetchError();
}
}
}
最后,在 UI 上的 onPressed 中, 您可以轻松做到:
context.read(userProvider).fetchUser(_phoneController.text.trim(),
_passwordController.text);
让我知道这是否适合你。