繁体   English   中英

使用 flutter_bloc 为 Flutter App 构建架构

[英]Build the architecture for a Flutter App with flutter_bloc

我必须用 Flutter 开发一个简单的应用程序,我第一次尝试使用 bloc 模式。 我正在使用flutter_bloc包,但我有两个主要问题并且卡住了:

  1. 应用程序中的所有屏幕都有依赖 repos 向服务器发出请求的块,并且对于每个请求,我都需要一个令牌。 我在authentication_bloc (登录)处获得了令牌,但我无法将该令牌共享给所有集团,除非我让它们依赖于 auth_bloc(拥有存储令牌的用户模型的集团)。 对于一个简单的应用程序,也许它可以工作,但是如果除了 auth_bloc 之外,其他 bloc 具有更多 bloc 依赖项,则将所有 bloc 作为依赖项注入可能会变得一团糟。 什么替代方案可能是一个好的解决方案?

  2. 对于导航我有一个bloc的底部导航栏。 但我希望选项卡上的所有屏幕都可以调用底部栏块的change_tab()函数。 又是同样的问题,如果其他块依赖于底部条块,我只能在底部条块中添加事件。 我不想添加 auth bloc 和底部栏 bloc 作为管理所有屏幕的所有 bloc 的依赖项。

我很欣赏建议、替代方案或文档,我可以在其中学习为比此处显示的示例更复杂的应用程序构建良好的架构

您可以将您的令牌存储在Repository例如userRepository.persistToken(event.token)await userRepository.deleteToken();
存储库的行为类似于存储库模式。 您不需要知道数据来自云端或本地数据库
在下面的示例中, userRepository 可以是应用程序级别,因此所有 bloc 都可以使用它
完整示例代码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在应用程序级别包装您的区块
下面的例子是地图和位置
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(),
          ),
      }
    );
  }
}

并使用它https://gitlab.kaleidos.net/piweek/betover/betover-mobile/blob/7b9368288743be602f37014f7a49ed4ef943afc1/lib/ui/widgets/map.dart

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 [];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM