标签: bloc

选择正确的 Flutter 设计模式

我创建了一个 Flutter 页面,其中有一堆输入。我认为这是一团糟,让我们重构它并为每个输入创建一个新的有状态小部件。

这很好,除了数据需要在父小部件中,而且我很难理解如何将数据从新的子小部件传递回父小部件。

我发现了一些方法,你传入一个函数,只要有变化,你就通过该函数将数据传递给父级。

我已经阅读了有关集团模式的内容,但我不确定这是否是我所需要的。我只想要一个单例样式对象,当有新输入时,主小部件及其子部件都可以读取并更新子部件。

有人能解释一下 bloc 模式是否会帮助我解决这个问题,或者是否有另一种设计模式可以帮助我解决这个问题。

** 编辑

谢谢你们的好答案。我的新问题与提供者模式/库有关。

我创建了一些状态类如下(我替换了内容以尝试保持简单)

class State1 with ChangeNotifier{

String _s;

  set s(String newS){
    _s = newS;
    notifyListeners();
  }

}

Run Code Online (Sandbox Code Playgroud)

然后我使用 multiprovider 来传递它(在 init 中创建对象)

child: MultiProvider(
        providers: [
          ChangeNotifierProvider(builder: (context) => state1),
        ],
        child: Stack(
        alignment: Alignment.center,
        children: stackChildren,
      ),
Run Code Online (Sandbox Code Playgroud)

然后使用子项widegets构建方法访问

 state1Var = Provider.of<State1>(context);

Run Code Online (Sandbox Code Playgroud)

所有这些都很好用..

我的问题是当我开始使用导航推送时,我无法再访问状态。

onPressed: (() {
          Navigator.push(
            contextField,
            MaterialPageRoute(builder: (context) => NewPage()),
          );
        }),
Run Code Online (Sandbox Code Playgroud)

当我收到此错误时

Could not find the correct Provider<State1> above this NewPage Widget...
Run Code Online (Sandbox Code Playgroud)

我确实设法使用它获得了它

  Navigator.push(
            context, …
Run Code Online (Sandbox Code Playgroud)

design-patterns flutter bloc

14
推荐指数
1
解决办法
1万
查看次数

Flutter 如何在没有 MediaQuery 的情况下获取亮度?

我的目标是创建一个应用程序,用户可以在其中选择他喜欢的主题。我使用共享首选项保存用户的选择,以便我可以在下次应用程序启动时加载它。用户可以选择: - 深色模式(独立于操作系统设置) - 浅色模式(独立于操作系统设置) - 系统(根据操作系统设置在深色模式和浅色模式之间进行更改) 在 BLoC 的帮助下,我几乎达到了我想要的。但问题是我需要在 Bloc 事件中传递亮度。为了获得系统(操作系统)亮度,我需要利用

MediaQuery.of(context).platformBrightness
Run Code Online (Sandbox Code Playgroud)

但 Bloc 在 MaterialApp 之前启动,因此 MediaQuery 不可用。当然,我可以稍后传递亮度(从 MaterialApp 的子小部件),但随后(例如,如果用户激活了黑暗模式)它会从亮到暗,但对用户来说可见的时间很短(因为在 InitialState 内)我在灯光模式下通过了)。

class MyApp extends StatelessWidget {
  final RecipeRepository recipeRepository;

  MyApp({Key key, @required this.recipeRepository})
      : assert(recipeRepository != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<ThemeBloc>(create: (context) =>
        ThemeBloc(),),

      ],
      child: BlocBuilder<ThemeBloc, ThemeState>(
        builder: (context, state){

          return MaterialApp(
            theme: state.themeData,
            title: 'Flutter Weather',
            localizationsDelegates: [
              FlutterI18nDelegate(fallbackFile: 'en',),
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate
            ],
            supportedLocales: [
              const Locale("en"), …
Run Code Online (Sandbox Code Playgroud)

dart flutter bloc ios-darkmode flutter-bloc

14
推荐指数
3
解决办法
7579
查看次数

什么是 copyWith 以及如何在 Flutter 中使用它以及它的用例是什么?

//File: email_sign_in_model.dart

class EmailSignInModel {
  EmailSignInModel({
    this.email='',
    this.formType=EmailSignInFormType.signIn,
    this.isLoading=false,
    this.password='',
    this.submitted=false,
  });

  final String email;
  final String password;
  final EmailSignInFormType formType;
  final bool isLoading;
  final bool submitted;

  EmailSignInModel copyWith({
    String email,
    String password,
    EmailSignInFormType formType,
    bool isLoading,
    bool submitted,

  }) {
    return EmailSignInModel(
    email: email ?? this.email,
    password: password?? this.password,
    formType: formType?? this.formType,
    isLoading: isLoading?? this.isLoading,
    submitted: submitted?? this.submitted

    );
  }
}



//File: email_sign_in_bloc.dart

import 'dart:async';
import 'package:timetrackerapp/app/sign_in/email_sign_in_model.dart';

class EmailSignInBloc {
 final StreamController<EmailSignInModel> _modelController = StreamController<EmailSignInModel>();
 Stream<EmailSignInModel> get modelStream => …
Run Code Online (Sandbox Code Playgroud)

forms stream dart flutter bloc

14
推荐指数
3
解决办法
6927
查看次数

Bloc 如何监听流并发出状态

在我的 flutter 应用程序中,我使用flutter_bloc进行状态管理。

bloc问题的使用repository. 订阅repositorywebsocket,并将新数据添加到流中。

问题:我的块监听流:

InvestmentClubBloc({
    required this.investmentClubRepository
  }) : super(InvestmentClubLoading()) {
    onChangeSubscription = investmentClubRepository.onNewMessage.listen(
      (event) {
        emit(NewMessageState(event); // <-- The member "emit" can only be used within 'package:bloc/src/bloc.dart' or in test
      },
    );
  }
Run Code Online (Sandbox Code Playgroud)

问题是emit不起作用(我收到警告“成员“emit”只能在 'package:bloc/src/bloc.dart' 或测试中使用”

bloc 如何监听流并根据流事件发出新状态?

flutter bloc flutter-bloc

14
推荐指数
2
解决办法
2万
查看次数

Flutter BLoC 多个 BLoC 相同的小部件

我对 Flutter 和 BLoC 模式比较陌生,所以我仍然试图把我的头脑围绕在所有事情上。

假设我有一个测验应用程序,其中有一个名为 BLoC 的应用程序,QuestionBloc它使用存储库从文件中获取问题。事件发生QuestionBloc

  • FetchQuestion

状态 QuestionBloc

  • QuestionEmpty
  • QuestionLoading
  • QuestionLoaded 其中包含一个问题对象
  • QuestionError

然后我调用了另一个 BLoC QuestionValidatorBloc,它负责验证问题的答案。答案被输入到一个文本字段中,并且有一个提交按钮来触发验证。事件发生QuestionValidatorBloc

  • ValidateQuestion

状态 QuestionValidatorBloc

  • ValidateInitial
  • ValidateInProgress
  • ValidateSuccess
  • ValidateError

这是相当直接的。不过,现在我需要二者结合QuestionBlocQuestionValidatorBloc在同一个部件,因为其中一人负责获取和显示问题和其他处理验证动作。我怎样才能做到这一点?

dart flutter bloc

13
推荐指数
1
解决办法
6453
查看次数

未为类型“BuildContext”定义方法“bloc”

 Widget build(BuildContext context) {
    final appBar = AppBar(
      title: Text(
        "Romantic Comedy",
      ),
      actions: [
        IconButton(
          icon: Icon(Icons.search),
          onPressed: () {
            showSearch(
                context: context,
                delegate: MaterialSearch(_pagingController.itemList));
          },
        ),
      ],
    );

    return Scaffold(
        backgroundColor: Colors.black,
        appBar: appBar,
        body: BlocConsumer<MovieBloc, MovieState>(
            listener: (context, movieState) {

            },
            builder: (context, movieState) {
              if (movieState is MovieSuccessState) {
                movieBloc.movies.addAll(movieState.movies);
              }
              return GridView.builder(
                  controller: _scrollController
                    ..addListener(() {
                      if (_scrollController.offset ==
                          _scrollController.position.maxScrollExtent) {
                        context.bloc<MovieBloc>()
                          ..isFetching = true
                          ..add(Fetch());
                      }
                    }),
                  padding: EdgeInsets.only(left: 12.0, right: 12.0),
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( …
Run Code Online (Sandbox Code Playgroud)

dart flutter bloc flutter-bloc

13
推荐指数
1
解决办法
6991
查看次数

如何在 BLOC、Cubit 和存储库中使用 flutter 国际化来翻译消息?

我正在 Flutter 中开发一个多语言应用程序。

我使用flutter_localizations包进行本地化,使用 intl包进行国际化。

以 Widgets 内的正常方式,我可以在Context的帮助下使用它。

但问题是当我想在存储库或除 UI 层之外的其他层中使用国际化时。

除了 UI(我们无法访问Context)之外的其他层中进行国际化的最佳实践是什么,例如在 Api、Repository、Bloc 或 Cubit 中使用国际化?

注意:我正在寻找一种在应用程序的 BLOC(业务逻辑)内部使用国际化的方法,而不是 UI!

localization internationalization flutter bloc cubit

13
推荐指数
1
解决办法
2798
查看次数

Bloc:是否有可能产生 2 次相同的状态?

在登录视图中,如果用户在没有插入凭据的情况下点击登录按钮,则 LoginFailState 为 yield 并且视图对其做出反应。如果他再次点击,这个 LoginFailstate 又是 yield ,但视图不会对它做出反应。那么,有没有办法在相同的状态下产生更多倍的结果?

有一些代码可以更好地解释我的情况:

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  @override
  LoginState get initialState => LoginUninitialized();

  @override
  Stream<LoginState> mapEventToState(LoginEvent event) {
    if (event is loginButtonPressed) {
      yield LoginFailState();
    }
  }
Run Code Online (Sandbox Code Playgroud)

看法:

 @override
  Widget build(BuildContext context) {
    return BlocBuilder(
      bloc: _loginBloc,
      builder: (BuildContext context, LoginState state) {
    if (state is LoginFail) {
        print ('Login fail');
    }
    return Column(
          ...
    )
Run Code Online (Sandbox Code Playgroud)

state handle flutter bloc

12
推荐指数
4
解决办法
5090
查看次数

Flutter BLoC:在 build() 方法中的 StreamBuilder 中的 Navigator.pop

我遵循 BLoC 模式并订阅流,并对构建方法中的状态变化做出反应。加载数据后,我想关闭屏幕。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Bloc'),
      ),
      body: SafeArea(
        child: StreamBuilder<UserState>(
          stream: _userBloc.user,
          initialData: UserInitState(),
          builder: (context, snapshot) {
            if (snapshot.data is UserInitState) {
              return _buildInit();
            }
            if (snapshot.data is UserDataState) {
              Navigator.pop(context, true);
              return Container();
            }
            if (snapshot.data is UserLoadingState) {
              return _buildLoading();
            }
          },
        ),
      ),
    );
  } 
Run Code Online (Sandbox Code Playgroud)

当我Navigator.pop(context, true);使用build()方法时,我得到:

I/flutter ( 4360): ??? EXCEPTION CAUGHT BY ANIMATION LIBRARY ??????????????????????????????????????????????????????????
I/flutter ( 4360): The following …
Run Code Online (Sandbox Code Playgroud)

flutter bloc

11
推荐指数
2
解决办法
4659
查看次数

Flutter 状态管理 (BloC):无状态与有状态小部件

所以我通读Bloc了状态管理flutter

由于 Bloc 允许您下沉和流式传输(根据输入重建小部件),那么是否有可能主要使用无状态小部件来构建应用程序?

例如,假设我制作了许多单个无状态类小部件,因此几乎所有东西都被划分为自己的无状态小部件。

使用 Bloc 状态管理,我可以简单地重建某个无状态的子小部件来反映更改。

在这种方法中,我认为不需要使用有状态小部件。当然,作为一个完全的初学者flutter,我想听听这种方法是否有任何优点。

这是一个好方法吗?任何信息将不胜感激。

stateless dart flutter bloc

11
推荐指数
2
解决办法
4464
查看次数