在我做了一个没有注解的项目之后,我正在用riverpod做一个有注解的项目。我已经尝试适应我在第一个项目中拥有的所有提供程序,但在访问_authNotifier. addsign时遇到了问题,因为它告诉我它没有定义。
我不知道发生了什么事,所以你能帮我会很有帮助的!
这是我的第一个项目的代码,它的工作完美
**auth_provider.dart**
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
final authRepository = AuthRepositoryImpl();
final keyValueStorageService = KeyValueStorageServiceImpl();
return AuthNotifier(
authRepository: authRepository,
keyValueStorageService: keyValueStorageService,
);
});
class AuthNotifier extends StateNotifier<AuthState> {
final AuthRepository authRepository;
final KeyValueStorageService keyValueStorageService;
AuthNotifier({
required this.authRepository,
required this.keyValueStorageService,
}) : super(AuthState()) {
checkAuthStatus();
}
Future<void> loginUser(String email, String password) async {
try {
final user = await authRepository.login(email, password);
_setLoggedUser(user);
} on CustomError catch (e) {
logout(e.message);
} catch (e) {
logout('Error no controlado');
}
}
void registerUser(String email, String password, String fullName) async {}
void checkAuthStatus() async {
final token = await keyValueStorageService.getKeyValue<String>('token');
if (token == null) return logout();
try {
final user = await authRepository.checkAuthStatus(token);
_setLoggedUser(user);
} catch (e) {
logout();
}
}
_setLoggedUser(User user) async {
await keyValueStorageService.setKeyValue('token', user.token);
state = state.copyWith(
user: user,
authStatus: AuthStatus.authenticated,
errorMessage: '',
);
}
Future<void> logout([String? errorMessage]) async {
await keyValueStorageService.removeKey('token');
state = state.copyWith(
authStatus: AuthStatus.unauthenticated,
user: null,
errorMessage: errorMessage,
);
}
}
enum AuthStatus { checking, authenticated, unauthenticated }
class AuthState {
final AuthStatus authStatus;
final User? user;
final String errorMessage;
AuthState({
this.authStatus = AuthStatus.checking,
this.user,
this.errorMessage = '',
});
AuthState copyWith({
AuthStatus? authStatus,
User? user,
String? errorMessage,
}) =>
AuthState(
authStatus: authStatus ?? this.authStatus,
user: user ?? this.user,
errorMessage: errorMessage ?? this.errorMessage,
);
}
**app_router_notifier.dart**
final goRouterNotifierProvider = Provider((ref) {
final authNotifier = ref.read(authProvider.notifier);
return GoRouterNotifier(authNotifier);
});
class GoRouterNotifier extends ChangeNotifier {
final AuthNotifier _authNotifier;
AuthStatus _authStatus = AuthStatus.checking;
GoRouterNotifier(this._authNotifier) {
_authNotifier.addListener((state) {
authStatus = state.authStatus;
});
}
AuthStatus get authStatus => _authStatus;
set authStatus(AuthStatus value) {
_authStatus = value;
notifyListeners();
}
}
这是我第二个使用注解的项目(问题在这里)
**auth_provider.dart**
part 'auth_provider.g.dart';
@Riverpod(keepAlive: true)
class Auth extends _$Auth {
final authRepository = AuthRepositoryImpl();
final keyValueStorageService = KeyValueStorageServiceImpl();
@override
AuthState build() {
checkAuthStatus();
return AuthState();
}
Future<void> loginUser(String email, String password) async {
try {
final user = await authRepository.login(email, password);
_setLoggedUser(user);
} on CustomError catch (e) {
logout(e.message);
} catch (e) {
logout('Error no controlado');
}
}
void registerUser(String email, String password, String username) async {}
void checkAuthStatus() async {
final token = await keyValueStorageService.getKeyValue<String>('token');
if (token == null) return logout();
try {
final user = await authRepository.checkAuthStatus(token);
_setLoggedUser(user);
} catch (e) {
logout();
}
}
_setLoggedUser(User user) async {
await keyValueStorageService.setKeyValue('token', user.token);
state = state.copyWith(
user: user,
authStatus: AuthStatus.authenticated,
errorMessage: '',
);
}
Future<void> logout([String? errorMessage]) async {
await keyValueStorageService.removeKey('token');
state = state.copyWith(
authStatus: AuthStatus.unauthenticated,
user: null,
errorMessage: errorMessage,
);
}
}
enum AuthStatus { checking, authenticated, unauthenticated }
class AuthState {
final AuthStatus authStatus;
final User? user;
final String errorMessage;
AuthState({
this.authStatus = AuthStatus.checking,
this.user,
this.errorMessage = '',
});
AuthState copyWith({
AuthStatus? authStatus,
User? user,
String? errorMessage,
}) =>
AuthState(
authStatus: authStatus ?? this.authStatus,
user: user ?? this.user,
errorMessage: errorMessage ?? this.errorMessage,
);
}
**app_router_notifier.dart**
part 'app_router_notifier.g.dart';
@Riverpod(keepAlive: true)
GoRouterNotifier goRouterNotifier(Ref ref) {
final authNotifier = ref.read(authProvider.notifier);
return GoRouterNotifier(authNotifier);
}
class GoRouterNotifier extends ChangeNotifier {
final Auth _authNotifier;
AuthStatus _authStatus = AuthStatus.checking;
GoRouterNotifier(this._authNotifier) {
_authNotifier.addListener((state) {
authStatus = state.authStatus;
});
}
AuthStatus get authStatus => _authStatus;
set authStatus(AuthStatus value) {
_authStatus = value;
notifyListeners();
}
}
那么问题是什么?
正如你所看到的,我正在尝试做完全相同的事情,但是在app_router_notifier.dart
中:
_authNotifier.addListener((state) {
authStatus = state.authStatus;
});
**我得到了这个错误:**方法'additive' is not defined for the type 'Auth'.尝试将名称更正为现有方法的名称,或定义名为“addListener”的方法。
我已经尝试了不同的解决方案,即使有人工智能,什么都没有。我想我的auth_provider.dart中有问题,但我不确定是什么。我相信.addListener
在StateNotifier
中,但它不在生成Riverpod的NotifierProvider中。
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'auth_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$authHash() => r'baf96bdb5085978702d0e2b04c3a2e56893b8a41';
/// See also [Auth].
@ProviderFor(Auth)
final authProvider = NotifierProvider<Auth, AuthState>.internal(
Auth.new,
name: r'authProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$authHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$Auth = Notifier<AuthState>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, inference_failure_on_uninitialized_variable, inference_failure_on_function_return_type, inference_failure_on_untyped_parameter
还有其他的“解决方案”对我不起作用:
_authNotifier.listen<AuthStatus>((state) {
authStatus = state.authStatus;
});
_authNotifier.ref.listen(authProvider.notifier, (_, currentState) {
authStatus = currentState.state.authStatus;
});
_authNotifier.addListener((state) {
final authState = _authNotifier.build();
authStatus = authState.authStatus;
});
应用的一点上下文
我正在使用Flutter,Dart,Riverpod和Go Router在我的后端(NestJS + GraphQL)进行登录和注册,在下面的文件中,如果没有有效的令牌,我将尝试重定向用户。下面是我使用goRouterNotifier的地方,这样它就可以在状态改变时监听并重定向用户。
part 'app_router.g.dart';
@Riverpod(keepAlive: false)
GoRouter goRouter(GoRouterRef ref) {
final goRouterNotifier = ref.read(goRouterNotifierProvider);
return GoRouter(
initialLocation: '/login',
refreshListenable: goRouterNotifier,
routes: [
//* First Route
GoRoute(
path: '/checking',
builder: (context, state) => const CheckAuthStatusScreen(),
),
//* Shared Routes
GoRoute(
path: '/main/:page',
builder: (context, state) {
final pageIndex = state.pathParameters['page'] ?? '0';
return MainScreen(pageIndex: int.parse(pageIndex));
}),
GoRoute(
path: '/settings',
builder: (context, state) => const SettingdScreen(),
),
//* Auth Routes
GoRoute(
path: '/login',
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: '/signup',
builder: (context, state) => const SignUpScreen(),
),
//* Home Routes
],
redirect: (context, state) {
// print(state.matchedLocation);
final isGoingTo = state.matchedLocation;
final authStatus = goRouterNotifier.authStatus;
if (isGoingTo == '/checking' && authStatus == AuthStatus.checking) {
return null;
}
if (authStatus == AuthStatus.unauthenticated) {
if (isGoingTo == '/login' || isGoingTo == '/signup') return null;
return '/login';
}
if (authStatus == AuthStatus.authenticated) {
if (isGoingTo == '/login' ||
isGoingTo == '/signup' ||
isGoingTo == '/checking') return '/main/0';
}
return null;
},
);
}
1条答案
按热度按时间hmae6n7t1#
实际上,
StateNotifier
属性(如.stream
或.addListener
)并不存在于Notifier
中。所以你应该这样听Notifier
:或者使用
ref.listen
方法(我认为在这种情况下这个选项是最佳的):您可以通过
GoRouterNotifier
类的构造函数将ref
传递给它。在任何其他情况下,如果您无法访问
ref
,请从上下文(ProviderScope.containerOf(context)
)获取当前容器并使用providerContainer.listen(provider)
。