have a Dart project using the Injectable
package for dependency injection. I'm facing a circular dependency issue between three classes: TokenInterceptor
, AuthRepository
, and ApiDatasource
, which leads to a stack overflow error during the initialization of dependencies.
The code structure is as follows:
register_module.dart:
@module
abstract class RegisterModule {
@lazySingleton
Dio dio() => Dio(
BaseOptions(baseUrl: Const.baseUrl),
)..interceptors.addAll(
[
LogInterceptor(),
TokenInterceptor(authRepository: ),
],
);
}
api_datasource.dart:
part 'api_datasource.g.dart';
@lazySingleton
@RestApi(baseUrl: Const.baseUrl)
abstract class ApiDatasource {
@POST('/identity/Auth/userRegister')
Future<void> registerUser(@Body() RegisterModel registerModel);
@POST('/identity/Auth/userLogin')
Future<void> loginUser(
@Body() LoginModel loginModel,
);
@GET('/identity/Auth/resetPassword')
Future<void> resetPassword(
@Body() ResetPasswordModel resetPasswordModel,
);
@GET('/identity/Auth/setNewPassword/{token}')
Future<void> setNewPassword(
@Path() String token,
@Body() SetNewPasswordModel setNewPasswordModel,
);
@GET('/pet/advertisements/shelters/{longitude}/{latitude}')
Future<List<PetModel>> getAdvertisement(
@Path('longitude') double longitude,
@Path('latitude') double latitude,
@Query('type') String type,
@Query('gender') String gender,
@Query('pageNumber') int pageNumber,
@Query('pageSize') int pageSize,
);
@GET('/pet/advertisements/shelters/{petId}/{longitude}/{latitude}')
Future<List<PetCardModel>> getDetailsAdvertisement(
@Path('longitude') double longitude,
@Path('latitude') double latitude,
@Path('petId') double petId,
);
}
token_interceptor.dart:
class TokenInterceptor extends Interceptor {
TokenInterceptor({required this.authRepository});
final AuthRepository authRepository;
@override
Future<void> onRequest(
RequestOptions options, RequestInterceptorHandler handler) async {
final String? token = await authRepository.accessToken;
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
}
}
auth_repository.dart:
const _accessTokenKey = 'access_token';
@lazySingleton
class AuthRepository {
AuthRepository(this.apiDatasource);
final LappkaApiDatasource apiDatasource;
String? _accessToken;
FutureOr<String?> get accessToken async {
if (_accessToken != null) {
return _accessToken;
}
return readAccessToken().then((token) {
_accessToken = token;
return token;
});
}
Future<String?> readAccessToken() async {
try {
const secureStorage = FlutterSecureStorage();
return secureStorage.read(key: _accessTokenKey);
} catch (e) {
return null;
}
}
Future<bool> saveToken(String token) async {
try {
const secureStorage = FlutterSecureStorage();
await secureStorage.write(key: _accessTokenKey, value: token);
_accessToken = token;
return true;
} catch (e) {
return false;
}
}
Future<void> registerUser(RegisterModel registerModel) async {
await apiDatasource.registerUser(registerModel);
}
Future<void> loginUser(LoginModel loginModel) async {
await apiDatasource.loginUser(loginModel);
}
Future<void> resetPassword(ResetPasswordModel resetPasswordModel) async {
await apiDatasource.resetPassword(resetPasswordModel);
}
Future<void> setNewPassword(
String token, SetNewPasswordModel setNewPasswordModel) async {
await apiDatasource.setNewPassword(token, setNewPasswordModel);
}
}
The TokenInterceptor
depends on AuthRepository
, and AuthRepository
depends on ApiDatasource
, which in turn depends on TokenInterceptor
, creating a circular dependency loop.
I have tried using Factory injection for TokenInterceptor
to defer its instantiation, but I still encounter the stack overflow issue.
How can I resolve this circular dependency and prevent the stack overflow during the dependency injection process?
Thank you for your help!
The solution is pretty simple. Just make another repository like token_repository
.