我正在做一个带注释的河荚项目,在我做了同样的项目后,没有注释.我试图调整我在第一个项目中拥有的所有提供程序,但在访问_authNotifier.addListener时遇到问题,因为它告诉我它尚未定义.

我不知道发生了什么事,所以你能帮我会很有帮助的!

This is my first project's code and it works perfect

**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();
  }
}

Now this is my second project using annotations (Here is the problem)

**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();
  }
}

So what is the problem?

正如你所看到的,我正试着做同样的事情,但在这条线上是app_router_notifier.dart:

_authNotifier.addListener((state) {
      authStatus = state.authStatus;
    });

I'm getting this error:没有为类型"Auth"定义方法"addListener". 请try 将名称更正为现有方法的名称,或定义名为"addListener"的方法.

我try 了不同的解决方案,即使是在人工智能方面也是如此.我认为我的auth_Provider.dart中有问题,但我不确定是什么问题.我相信.addListenerStateNotifier中,但它不在生成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;
    });

A little bit of context of the application

我正在后端(NestJS+GraphQL)使用Ffltter、Dart、Riverpod和Go Router进行登录和注册,在下面的文件中,如果没有有效的令牌,我将try 重定向用户.这就是我使用goRouterNotify的地方,这样它就可以在状态更改时侦听并重定向用户.

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;
    },
  );
}

推荐答案

事实上,像.stream.addListener这样的StateNotifier个属性在Notifier中并不存在.所以你应该像这样听Notifier:

_authNotifier.ref.listenSelf((AuthState? previous, AuthState next) {
      authStatus = next.authStatus;
    });

或使用ref.listen方法(I think this option is the most optimal in this situation):

ref.listen(_authNotifier, (AuthState? previous, AuthState next) {
      authStatus = next.authStatus;
    });

您可以通过GoRouterNotifier类的构造函数将ref传递给它.

在您无法访问ref的任何其他情况下,从上下文(ProviderScope.containerOf(context))获取当前容器并使用providerContainer.listen(provider).

Flutter相关问答推荐

错误:找不到字体功能类型.Ffltter Google_Fonts包错误

如何在Flutter 中播放音频

Flutter -如何停止块监听程序在后台堆栈中运行

Flutter 动画列表一次构建所有项目,而不是仅构建可见的项目

我有相关的下拉菜单Flutter Windows应用程序的问题

无法在我的Flutter 应用程序中使用GoRouter测试导航

Flutter 渲染HTML和数学(LaTeX和Katex)

从Firestore流式传输单个文档还是整个集合更好?

Flutter Xcode 15 错误(Xcode):DT_TOOLCHAIN_DIR 无法用于判断 LIBRARY_SEARCH_PATHS

Flutter 未处理的异常 - 对 null 值使用 Null 判断运算符

尽管设置了对齐方式,如何对齐列中的行?

在flutter中从图库或相机中 Select 图像的方法

如何在 Flutter (iOS) 中解决这个问题

Flutter/Riverpod 创建复杂对象的副本,其值在某处发生变化

为什么 appBar 小部件在 flutter 中不是常量

如何在 Flutter 中滚动时为多个小部件设置动画

如何按值对列表中的 map 进行排序

如何在Flutter中制作带有波浪边框的圆圈来显示图像?

有任何方法可以在应用程序移动背景恢复时显示 appopenAd

Flutter 广告导致延迟