我正在努力弄清楚为什么这不起作用(而不是说明它应该起作用的文档)。
我有一个像这样的提供者
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:putin_flutter_client/api/client.dart';
import 'package:putin_flutter_client/api/storage.dart';
final userProvider = StateNotifierProvider((_) => UserNotifier());
class UserNotifier extends StateNotifier<UserState> {
UserNotifier() : super(UserState());
set username(String username) {
state = UserState(username: username, password: state.password, jwt: state.jwt);
secureStorageWrite('username', username);
}
set password(String password) {
state = UserState(username: state.username, password: password, jwt: state.jwt);
secureStorageWrite('password', password);
}
set jwt(String jwt) {
state = UserState(username: state.username, password: state.password, jwt: jwt);
Client.jwt = jwt;
secureStorageWrite('jwt', jwt);
}
String get jwt {
return state.jwt;
}
Future<void> initState() async {
final user = await UserState.load();
state.username = user.username;
state.password = user.password;
state.jwt = user.jwt;
}
}
class UserState {
String username;
String password;
String jwt;
UserState({
this.username,
this.password,
this.jwt,
});
static Future<UserState> load() async {
return UserState(
username: await secureStorageRead('username'),
password: await secureStorageRead('password'),
jwt: await secureStorageRead('jwt'),
);
}
}
最终深入一些小部件,这样的事情会更新状态
// usilizing the setter on the provider to update the state...
user.jwt = data['token'];
现在在代码的其他部分我管理 http 客户端。这显然无法访问BuildContext
等,因此我执行以下操作以从存储状态中检索 jwt 值。
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:putin_flutter_client/state/user.dart';
class Client extends http.BaseClient {
final http.Client _client = http.Client();
Future<http.StreamedResponse> send(http.BaseRequest request) {
// Get the container as per riverpod documentation
final container = ProviderContainer();
// Access the value through the getter on the provider
final jwt = container.read(userProvider).jwt;
request.headers['user-agent'] = 'myclient::v1.0.0';
request.headers['Content-Type'] = 'application/json';
if (jwt != null) {
request.headers['X-Auth-Token'] = jwt;
}
return _client.send(request);
}
}
这始终为空,并且 UserState 几乎为空(所有成员都为空)。
在Riverpod 文档中,它说这应该有效
test('counter starts at 0', () {
final container = ProviderContainer();
StateController<int> counter = container.read(counterProvider);
expect(counter.state, 0);
});
有人可以帮我弄清楚上面的例子有什么问题吗?
ProviderContainer() 为您的提供者创建一个新实例,它不会获得实际状态。您需要让您的客户端依赖于这样的用户状态:
final clientProvider = Provider<Client>((ref){
return Client(ref.watch(userProvider.state))
});
class Client extends http.BaseClient {
Client(this._userState);
final UserState _userState;
final http.Client _client = http.Client();
Future<http.StreamedResponse> send(http.BaseRequest request) {
final jwt = _userState.jwt;
request.headers['user-agent'] = 'myclient::v1.0.0';
request.headers['Content-Type'] = 'application/json';
if (jwt != null) {
request.headers['X-Auth-Token'] = jwt;
}
return _client.send(request);
}
}
当您的用户状态发生变化时,客户端将使用新值重新实例化
如果您不想每次都重新实例化,则改为通过 read 方法:
final clientProvider = Provider<Client>((ref){
return Client(ref.read)
});
class Client extends http.BaseClient {
Client(this._reader);
final Reader _reader;
final http.Client _client = http.Client();
Future<http.StreamedResponse> send(http.BaseRequest request) {
final jwt = _reader(userProvider.state).jwt;
request.headers['user-agent'] = 'myclient::v1.0.0';
request.headers['Content-Type'] = 'application/json';
if (jwt != null) {
request.headers['X-Auth-Token'] = jwt;
}
return _client.send(request);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句