ref.listen 方法不调用作为参数给出的方法
ref.listen method doesn't call one that is given as a parameter
我使用 Riverpod 进行状态管理
我想查看 StateNotifier<LoginNotifierData>
共享的字符串消息。我在 ConsumerState<LoginScreen>
中调用 ref.listen
。但是虽然state.message
在改,ref.listen
里面的Function并没有被调用。我的问题是,为什么在更改 state
时不调用作为 ref.listen()
第二个参数给出的函数。
我使用 Equatable 库来比较对象
当我观察整个 LoginNotifierData 对象(没有 loginModelStateNotifierProvider.select()
)时,它也不起作用
通知程序中的登录方法(它更改了 state
):
void login(String username, String password, WidgetRef ref) async {
state.message = "Logowanie...";
Either<Failure, LoginModel> setLogin = await ref
.read(loginUseCaseProvider)
.call(LoginParams(
username: username,
password: password));
setLogin.fold((failure) {
log('API Login: failure');
state.message = failure.message;
log(failure.toString());
}, (loginModel) {
log('API Login: success=${loginModel.success}');
if (loginModel.success) {
ref
.read(loginModelStateNotifierProvider.notifier)
.setLoginModel(loginModel);
_storeUserData(loginModel, ref);
ref.read(userRepositoryProvider).storeUsername(username);
ref.read(userRepositoryProvider).storePassword(password);
state.message = "";
} else {
state.message = loginModel.message;
log('responseCode: ${loginModel.responseCode}');
}
});
}
LoginNotifierData(state
属于这种类型)
class LoginNotifierData extends Equatable {
LoginModel loginModel = LoginModel("", 0, "", false, "", "", "", false, 0.0, "", "");
String message = "";
LoginNotifierData(this.loginModel, this.message);
@override
List<Object?> get props => [loginModel, message];
}
ref.listen 在 ConsumerState
的 @override Widget build
方法中调用
ref.listen<String>(
loginModelStateNotifierProvider.select((value) => value.message),
(_, message) {
if(message.isNotEmpty) {
widget.showLoaderDialog(context, message);
} else {
widget.hideDialog();
}
}
);
loginModelStateNotifierProvider:
final loginModelStateNotifierProvider =
StateNotifierProvider<LoginModelStateNotifier, LoginNotifierData>(
(ref) => LoginModelStateNotifier()
);
您无法通过 StateNotifier
中的 re-assigning 属性更新 state
...您必须 re-assign state
本身。
使用 copyWith
方法可以做到这一点。
按照以下步骤操作:
1.在LoginNotifierData
中创建一个copyWith
方法
class LoginNotifierData extends Equatable {
LoginModel loginModel = LoginModel("", 0, "", false, "", "", "", false, 0.0, "", "");
String message = "";
LoginNotifierData(this.loginModel, this.message);
LoginNotifierData copyWith({LoginModel? loginModel, String? message}){
return LoginNotifierData(
loginModel: loginModel,
message: message,
);
}
@override
List<Object?> get props => [loginModel, message];
}
2。使用 copy with 方法 re-assign StateNotifier
中的状态
void login(String username, String password, WidgetRef ref) async {
state = state.copyWith(message: "Logowanie...");
Either<Failure, LoginModel> setLogin = await ref
.read(loginUseCaseProvider)
.call(LoginParams(
username: username,
password: password));
setLogin.fold((failure) {
log('API Login: failure');
state = state.copyWith(message: failure.message);
log(failure.toString());
}, (loginModel) {
log('API Login: success=${loginModel.success}');
if (loginModel.success) {
ref
.read(loginModelStateNotifierProvider.notifier)
.setLoginModel(loginModel);
_storeUserData(loginModel, ref);
ref.read(userRepositoryProvider).storeUsername(username);
ref.read(userRepositoryProvider).storePassword(password);
state = state.copyWith(message: "");
} else {
state = state.copyWith(message: loginModel.message);
log('responseCode: ${loginModel.responseCode}');
}
});
}
我使用 Riverpod 进行状态管理
我想查看 StateNotifier<LoginNotifierData>
共享的字符串消息。我在 ConsumerState<LoginScreen>
中调用 ref.listen
。但是虽然state.message
在改,ref.listen
里面的Function并没有被调用。我的问题是,为什么在更改 state
时不调用作为 ref.listen()
第二个参数给出的函数。
我使用 Equatable 库来比较对象
当我观察整个 LoginNotifierData 对象(没有 loginModelStateNotifierProvider.select()
)时,它也不起作用
通知程序中的登录方法(它更改了 state
):
void login(String username, String password, WidgetRef ref) async {
state.message = "Logowanie...";
Either<Failure, LoginModel> setLogin = await ref
.read(loginUseCaseProvider)
.call(LoginParams(
username: username,
password: password));
setLogin.fold((failure) {
log('API Login: failure');
state.message = failure.message;
log(failure.toString());
}, (loginModel) {
log('API Login: success=${loginModel.success}');
if (loginModel.success) {
ref
.read(loginModelStateNotifierProvider.notifier)
.setLoginModel(loginModel);
_storeUserData(loginModel, ref);
ref.read(userRepositoryProvider).storeUsername(username);
ref.read(userRepositoryProvider).storePassword(password);
state.message = "";
} else {
state.message = loginModel.message;
log('responseCode: ${loginModel.responseCode}');
}
});
}
LoginNotifierData(state
属于这种类型)
class LoginNotifierData extends Equatable {
LoginModel loginModel = LoginModel("", 0, "", false, "", "", "", false, 0.0, "", "");
String message = "";
LoginNotifierData(this.loginModel, this.message);
@override
List<Object?> get props => [loginModel, message];
}
ref.listen 在 ConsumerState
的@override Widget build
方法中调用
ref.listen<String>(
loginModelStateNotifierProvider.select((value) => value.message),
(_, message) {
if(message.isNotEmpty) {
widget.showLoaderDialog(context, message);
} else {
widget.hideDialog();
}
}
);
loginModelStateNotifierProvider:
final loginModelStateNotifierProvider =
StateNotifierProvider<LoginModelStateNotifier, LoginNotifierData>(
(ref) => LoginModelStateNotifier()
);
您无法通过 StateNotifier
中的 re-assigning 属性更新 state
...您必须 re-assign state
本身。
使用 copyWith
方法可以做到这一点。
按照以下步骤操作:
1.在LoginNotifierData
copyWith
方法
class LoginNotifierData extends Equatable {
LoginModel loginModel = LoginModel("", 0, "", false, "", "", "", false, 0.0, "", "");
String message = "";
LoginNotifierData(this.loginModel, this.message);
LoginNotifierData copyWith({LoginModel? loginModel, String? message}){
return LoginNotifierData(
loginModel: loginModel,
message: message,
);
}
@override
List<Object?> get props => [loginModel, message];
}
2。使用 copy with 方法 re-assign StateNotifier
中的状态void login(String username, String password, WidgetRef ref) async {
state = state.copyWith(message: "Logowanie...");
Either<Failure, LoginModel> setLogin = await ref
.read(loginUseCaseProvider)
.call(LoginParams(
username: username,
password: password));
setLogin.fold((failure) {
log('API Login: failure');
state = state.copyWith(message: failure.message);
log(failure.toString());
}, (loginModel) {
log('API Login: success=${loginModel.success}');
if (loginModel.success) {
ref
.read(loginModelStateNotifierProvider.notifier)
.setLoginModel(loginModel);
_storeUserData(loginModel, ref);
ref.read(userRepositoryProvider).storeUsername(username);
ref.read(userRepositoryProvider).storePassword(password);
state = state.copyWith(message: "");
} else {
state = state.copyWith(message: loginModel.message);
log('responseCode: ${loginModel.responseCode}');
}
});
}