EDIT
使用 bloc 提供的方法进行依赖注入,而不是 get_it。创建单例可能是一个问题,因为它不会自动处理。BlocProvider
处理和处置创建的块,如文档中所述
在大多数情况下,BlocProvider 应该用于创建新的块,这些块将可供子树的其余部分使用。在这种情况下,由于 BlocProvider 负责创建块,因此它将自动处理关闭块。
And use BlocProvider.value
按照 bloc 官方建议传递值文档 https://bloclibrary.dev/#/flutterbloccoreconcepts?id=blocprovider.
BlocProvider(
create: (BuildContext context) => BlocA(service1: sl<Service1>()),
child: ChildA(),
);
这就是我一起使用 BlocProvider 和 get_it 的方式。我将 get_it 用于除 Bloc 之外的所有内容。而bloc的参数是由get_it的依赖注入提供的。
如果你想使用 get_it,请阅读 TLDR;部分。
TLDR;
Use Singleton
仅在必要时(AuthenticationBloc
)。并继续使用Factory
对于所有其他集团(LoginBloc
, etc).
final sl = GetIt.instance;
final Environment _env = Environment();
Future<void> init() async {
//! Core
..load some singletons
//! Bloc
sl.registerLazySingleton(() => AuthenticationBloc(secureStorage: sl()));
sl.registerFactory(() => LoginBloc(authenticationBloc: sl(), authService: sl()));
sl.registerFactory(() => SignupBloc(authenticationBloc: sl(), authService: sl()));
}
Concepts
我在使用 bloc 时使用相同的方法。我们遇到的需要两个块进行通信的最常见情况是 AuthenticationBloc 与几乎所有其他块进行通信。
Why registerFactory
不工作。但registerLazySingleton
does
getit 的定义为registerFactory
您必须传递一个工厂函数 func,它返回 T 实现的新实例。每次调用 get() 时,您都会返回一个新实例
根据 get_it 文档。registerFactory
每次我们调用时都会生成一个 Bloc 对象的新实例sl<AuthenticationBloc>()
方法。
现在,当LoginBloc
构造函数要求一个参数,我们传递sl()
在我们的依赖注入文件中,我们正在创建一个新实例并将其传递给我们的LoginBloc
。因此AuthenticationBloc
我们的应用程序中使用的实例不等于AuthenticationBloc
我们已经提供给我们的LoginBloc
构造函数。结果你的AuthenticationBloc
不会听取所传达的更改LoginBloc
因为它将事件添加到了其他一些实例AuthenticationBloc
.
registerLazySingleton
定义为
您必须传递一个返回 T 实现实例的工厂函数 func。只有在您第一次调用 get() 时,才会调用此工厂函数来创建新实例。
如上所述,简单的解决方案是将依赖注入从registerFactory
to registerLazySingleton
。通过这样做,您将提供一个实例AuthenticationBloc
整个申请过程中。因此事件添加到AuthenticationBloc
from LoginBloc
将开始工作。
建议的解决方案
可以有两种解决方案。一是这个问题中提出的,即将每个集团更改为lazySingleton
。但它不会在需要时创建新的集团。通过使用该方法,您将在整个应用程序中使用相同的 Bloc 实例。它适用于大多数情况。
另一种方法是使Singleton
仅在必要时(AuthenticationBloc
)。并继续使用Factory
对于所有其他集团(LoginBloc
, etc).
认证块
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final SecureStorage secureStorage;
AuthenticationBloc({required this.secureStorage}) : super(AppInitial());
@override
Stream<AuthenticationState> mapEventToState(AuthenticationEvent event) async* {
if (event is AppStarted) {
AuthModel? authModel = await secureStorage.getAuthUser();
if (authModel != null && authModel.jwtToken.isNotEmpty && authModel.userId.isNotEmpty) {
yield AuthenticationUserKnown(authModel: authModel);
} else {
yield AuthenticationUserUnknown();
}
} else if (event is UserAuthenticated) {
yield AuthenticationUserKnown(authModel: event.authModel);
} else if (event is UserLoggedOut) {
yield AuthenticationUserUnknown();
}
}
}
登录区块
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc({required this.authenticationBloc, required this.validationHelper, required this.authService})
: super(LoginInitial());
final AuthenticationBloc authenticationBloc;
final AuthService authService;
final ValidationHelper validationHelper;
@override
Stream<LoginState> mapEventToState(LoginEvent event) async* {
if (event is EmailAuthenticationRequested) {
yield* _mapEmailAuthencationRequestedEventToState(event);
}
}
Stream<LoginState> _mapEmailAuthencationRequestedEventToState(EmailAuthenticationRequested event) async* {
yield AuthenticationInProgress();
final authEither = await authService.loginWithEmail(email: event.email, password: event.password);
yield authEither.fold(
(failure) => LoginAuthenticationFailure(failureMessage: failure.errorMessage),
(authModel) {
authenticationBloc.add(UserAuthenticated(authModel: authModel));
return LoginAuthenticationSuccess(authModel: authModel, authenticationMethod: AuthenticationMethod.EMAIL);
},
);
}
@override
Future<void> close() {
authenticationBloc.close();
return super.close();
}
}
依赖注入器
final sl = GetIt.instance;
final Environment _env = Environment();
Future<void> init() async {
//! Core
..load some singletons
//! Bloc
sl.registerLazySingleton(() => AuthenticationBloc(secureStorage: sl()));
sl.registerFactory(() => LoginBloc(authenticationBloc: sl(), validationHelper: sl(), authService: sl()));
sl.registerFactory(() => SignupBloc(validationHelper: sl(), authService: sl()));
}