我必须使用 Flutter 开发一个简单的应用程序,并且我正在第一次尝试 bloc 模式。我正在使用 flutter_bloc
包,但我有两个主要问题并陷入困境:
应用程序中的所有屏幕都有依赖于存储库向服务器发出请求的 block ,对于每个请求我都需要一个 token 。我在
authentication_bloc
(登录)处获取 token ,但我无法将该 token 共享给所有 block ,除非我使它们依赖于 auth_bloc(具有存储 token 的用户模型的 block )。对于一个简单的应用程序,也许它可以工作,但是如果除了 auth_bloc 之外,其他 block 还有更多的 block 依赖项,那么将所有 block 作为依赖项注入(inject)可能会变得一团糟。什么替代方案可能是一个好的解决方案?对于导航,我有一个用于底部导航栏的
bloc
。但我希望选项卡上的所有屏幕都可以调用底部栏 block 的change_tab()
函数。同样的问题,如果其他 block 依赖于底部栏 block ,我只能在底部栏 block 添加事件。我不想将身份验证 block 和底部栏 block 添加为管理所有屏幕的所有 block 的依赖项。
我很欣赏建议、替代方案或文档,我可以在其中学习为比示例显示的稍微复杂一点的应用程序构建良好的架构 here
最佳答案
您可以将 token 存储在Repository
中,例如userRepository.persistToken(event.token)
和await userRepository.deleteToken();
< br/>
存储库的行为类似于存储库模式。您不需要知道数据来自云端还是本地数据库
在下面的示例中,userRepository 可以是应用程序级别,因此所有 block 都可以使用它
完整示例代码 https://github.com/felangel/bloc/blob/master/examples/flutter_login/lib/authentication/authentication_bloc.dart
代码片段
void main() {
BlocSupervisor.delegate = SimpleBlocDelegate();
final userRepository = UserRepository();
runApp(
BlocProvider<AuthenticationBloc>(
create: (context) {
return AuthenticationBloc(userRepository: userRepository)
..add(AppStarted());
},
child: App(userRepository: userRepository),
),
);
}
...
import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import 'package:user_repository/user_repository.dart';
import 'package:flutter_login/authentication/authentication.dart';
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository userRepository;
AuthenticationBloc({@required this.userRepository})
: assert(userRepository != null);
@override
AuthenticationState get initialState => AuthenticationUninitialized();
@override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is AppStarted) {
final bool hasToken = await userRepository.hasToken();
if (hasToken) {
yield AuthenticationAuthenticated();
} else {
yield AuthenticationUnauthenticated();
}
}
if (event is LoggedIn) {
yield AuthenticationLoading();
await userRepository.persistToken(event.token);
yield AuthenticationAuthenticated();
}
if (event is LoggedOut) {
yield AuthenticationLoading();
await userRepository.deleteToken();
yield AuthenticationUnauthenticated();
}
}
}
您可以使用 MultiBlocProvider
在应用程序级别包装您的 block
下面的例子是 map 和位置
https://gitlab.kaleidos.net/piweek/betover/betover-mobile/blob/7b9368288743be602f37014f7a49ed4ef943afc1/lib/main.dart
void main() {
BlocSupervisor.delegate = SimpleBlocDelegate();
runApp(
MultiBlocProvider(
providers: [
BlocProvider<MapBloc>(
create: (context) => MapBloc(),
),
BlocProvider<PoisBloc>(
create: (context) => PoisBloc(
mapBloc: BlocProvider.of<MapBloc>(context),
),
),
],
child: App(),
)
);
}
class App extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Bet Over',
theme: appTheme,
initialRoute: '/',
routes: {
'/': (context) =>
MultiBlocProvider(
providers: [
BlocProvider<MapBloc>(
create: (context) => BlocProvider.of<MapBloc>(context),
),
BlocProvider<PoisBloc>(
create: (context) => BlocProvider.of<PoisBloc>(context),
),
],
child: MapPage(),
),
'/create-poi': (context) =>
MultiBlocProvider(
providers: [
BlocProvider<MapBloc>(
create: (context) => BlocProvider.of<MapBloc>(context),
),
BlocProvider<PoisBloc>(
create: (context) => BlocProvider.of<PoisBloc>(context),
),
],
child: CreatePoimPage(),
),
}
);
}
}
class _MapState extends State<Map> {
MapBloc _mapBloc;
PoisBloc _poisBloc;
@override
void initState() {
super.initState();
_mapBloc = BlocProvider.of<MapBloc>(context);
_poisBloc = BlocProvider.of<PoisBloc>(context);
...
List<Marker> _generateMarkers () {
if (!(_mapBloc.state is MapViewboxChanged && _poisBloc.state is PoisLoaded))
return [];
关于flutter - 使用 flutter_bloc 构建 Flutter 应用程序的架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59621809/