【发布时间】:2020-09-03 04:28:23
【问题描述】:
我一直在结合使用此登录教程和 resocoder 清洁架构教程来构建登录/身份验证功能。它 99% 工作正常,但它无法正确响应按下的 LoginButton。
由于某种原因,当LoginBloc 调用AuthenticationBloc.add(loggedin()) 时,AuthenticationBloc 产生AuthenticationAuthenticated() 状态就好了,但 Main.dart 中的BlocBuilder 没有收到状态更改。当产生AuthenticationAuthenticated 时,即使是SimpleBlocDelegate 中的OnTransition 也会被触发,但BlocBuilder 什么也不做。
Main.dart 看起来像这样:
import 'package:bloc/bloc.dart';
import 'package:flutter_app/dependency_injector.dart' as di;
import 'package:flutter_app/features/login/presentation/pages/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'features/login/presentation/bloc/user_login_bloc.dart';
import 'features/login/presentation/bloc/user_login_events.dart';
import 'features/login/presentation/bloc/user_login_states.dart';
class SimpleBlocDelegate extends BlocDelegate {
@override
void onEvent(Bloc bloc, Object event) {
print(event);
super.onEvent(bloc, event);
}
@override
void onTransition(Bloc bloc, Transition transition) {
print(transition);
super.onTransition(bloc, transition);
}
@override
void onError(Bloc bloc, Object error, StackTrace stackTrace) {
print(error);
super.onError(bloc, error, stackTrace);
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await di.init(); //Dependency Injection using get_it
BlocSupervisor.delegate = SimpleBlocDelegate();
runApp(
BlocProvider<UserAuthenticationBloc>(
create: (_) => sl<UserAuthenticationBloc>()..add(AppStarted()),
child: App(),
),
);
}
class App extends StatelessWidget {
App({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocBuilder<UserAuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationAuthenticated) {
return Container(
child: HomePage(); // THIS NEVER HAPPENS, even though AuthBloc yields the State
}
if (state is AuthenticationUnauthenticated) {
return LoginScreen(); // THIS yeilds fine when AppStarted in passed on init.
}
if (state is AuthenticationLoading) {
return LoadingIndicator();
}
return Scaffold(
body: SplashPage();
)
},
),
);
}
}
我只能认为它与get_it 有关。依赖注入看起来像这样:
final sl = GetIt.instance;
Future<void> init() async {
sl.registerFactory(
() => UserAuthenticationBloc(
getCachedUser: sl(),
),
);
sl.registerFactory(
() => LoginBloc(authenticationBloc: sl(), getUserFromEmailAndPassword: sl()),
);
...
}
然后在loginscreen 的小部件树中创建LoginBloc,因此它可用于登录表单。
class LoginScreen extends StatelessWidget {
LoginScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider<LoginBloc>(
create: (_) => sl<LoginBloc>(),
child: LoginForm(), //login form
),
);
}
}
两个编辑:
1.我将依赖注入文件中的UserAuthenticationBloc从工厂更改为lazysingleton......现在它可以工作了。但是,我听说对带有 Streams 的类使用单例会导致内存泄漏??我想这意味着 LoginBloc 没有与 Main.dart 正在听的 AuthBloc 的同一个实例交谈?我不知道如何确保没有单例......
- UserAuthenticationBloc 代码:
class UserAuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final GetCachedUser getCachedUser;
UserAuthenticationBloc({
@required GetCachedUser getCachedUser,
}) : assert(getCachedUser != null),
getCachedUser = getCachedUser;
@override
AuthenticationState get initialState => AuthenticationUninitialized();
@override
Stream<AuthenticationState> mapEventToState(AuthenticationEvent event) async* {
if (event is AppStarted) {
yield AuthenticationUnauthenticated();
}
}
if (event is LoggedIn) {
yield AuthenticationAuthenticated(); //this fires.
}
}
}
【问题讨论】:
-
可以分享
UserAuthenticationBloc的代码 -
@SanjaySharma 已添加。
-
AuthenticationState是否继承Equatable? -
@SanjaySharma 是的。
-
@M-Solutions 恐怕我再也找不到更多信息了。我继续我正在做的事情,现在在应用程序中以这种方式设置了 5 个区块。到目前为止,性能似乎还不错。
标签: flutter bloc service-locator