flutter_block:BlockProvider 与 RepositoryProvider

Posted

技术标签:

【中文标题】flutter_block:BlockProvider 与 RepositoryProvider【英文标题】:flutter_block: BlockProvider vs. RepositoryProvider 【发布时间】:2020-04-23 04:09:38 【问题描述】:

我想澄清一下BlocProviderRepositoryProvider。从官方 API 参考来看,它们提供了相同的功能 - 它们向其后代小部件提供对象的实例。

但是,从名称来看,我猜 BlocProvider 应该仅用于 Bloc 对象,RepositoryProvider 用于其他所有对象。这是正确的吗?

【问题讨论】:

【参考方案1】:

RepositoryProvider 的行为类似于 Repository 模式 它的 Data Provider 向 Bloc 提供数据,因此 Bloc 不需要知道数据来自云或 sqflite 或 ... 并进行合并/过滤,请参见下面的官方示例

在下面的 LoginForm 示例中 存储库是 Bloc 的一部分,您可以使用 _userRepository.login

class LoginFormBloc extends FormBloc<String, String> 
      final emailField = TextFieldBloc(validators: [Validators.email]);
      final passwordField = TextFieldBloc();

      final UserRepository _userRepository;

      LoginFormBloc(this._userRepository);

      @override
      List<FieldBloc> get fieldBlocs => [emailField, passwordField];

      @override
      Stream<FormBlocState<String, String>> onSubmitting() async* 
        try 
          _userRepository.login(
            email: emailField.value,
            password: passwordField.value,
          );
          yield currentState.toSuccess();
         catch (e) 
          yield currentState.toFailure();
        
      
    

您可以将您的存储库注入 Bloc 代码sn-p

class LoginForm extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return BlocProvider<LoginFormBloc>(
      builder: (context) =>
          LoginFormBloc(RepositoryProvider.of<UserRepository>(context)),
      child: Builder(
        builder: (context) 
          final formBloc = BlocProvider.of<LoginFormBloc>(context);

          return Scaffold(
            appBar: AppBar(title: Text('Simple login')),
            body: FormBlocListener<LoginFormBloc, String, String>(
              onSubmitting: (context, state) => LoadingDialog.show(context),
              onSuccess: (context, state) 
                LoadingDialog.hide(context);
                Navigator.of(context).pushReplacementNamed('success');
              ,
              onFailure: (context, state) 
                LoadingDialog.hide(context);
                Notifications.showSnackBarWithError(
                    context, state.failureResponse);
              ,

你可以参考https://flutterawesome.com/create-beautiful-forms-in-flutter/

官方例子https://bloclibrary.dev/#/architecture bloc 层可以依赖一个或多个存储库来检索构建应用程序状态所需的数据。

class Repository 
    final DataProviderA dataProviderA;
    final DataProviderB dataProviderB;

    Future<Data> getAllDataThatMeetsRequirements() async 
        final RawDataA dataSetA = await dataProviderA.readData();
        final RawDataB dataSetB = await dataProviderB.readData();

        final Data filteredData = _filterData(dataSetA, dataSetB);
        return filteredData;
    


class BusinessLogicComponent extends Bloc<MyEvent, MyState> 
    final Repository repository;

    Stream mapEventToState(event) async* 
        if (event is AppStarted) 
            try 
                final data = await repository.getAllDataThatMeetsRequirements();
                yield Success(data);
             catch (error) 
                yield Failure(error);
            
        
    

【讨论】:

【参考方案2】:

简单回答

与 BlocProvider 相同。

BlockProvider 通过 BlockProvider.of(context) 将块提供给它的孩子。在大多数情况下,开发人员会创建一个新的 BlocProvider 并可供子树的其余部分使用。

现在来到 RepositoryProvider

RepositoryProvider 通过 RepositoryProvider.of(context) 向其子项提供存储库。当开发人员创建一个新的 RepositoryProvider 并且它可用于子树的其余部分时。

【讨论】:

以上是关于flutter_block:BlockProvider 与 RepositoryProvider的主要内容,如果未能解决你的问题,请参考以下文章