【问题标题】:Why is this bloc getter called on null?为什么这个 bloc getter 在 null 上调用?
【发布时间】:2019-09-12 18:29:22
【问题描述】:

以前我在 main.dart 中初始化我的 PersonBlocProvider

return PersonBlocProvider(
        personBloc: PersonBloc(this._apiInterface),
        child: AlarmBlocProvider(
            alarmBloc: AlarmBloc(this._apiInterface),
            child: EventBlocProvider(
                eventBloc: EventBloc(this._apiInterface),
                child: MaterialApp(
                  title: 'Hat Mobile',
                  theme: ThemeData(
                    primarySwatch: Colors.green,
                  ),
                  home: LoginScreen(),
                )

            )
        )
    );

在另一个视图中使用 BLOC,如下所示:

class AlarmView extends StatelessWidget {
  Widget build(BuildContext context) {
    final personBlocProvider = PersonBlocProvider.of(context);
    final alarmBlocProvider = AlarmBlocProvider.of(context);

    return
        DefaultTabController(
        length: 4,
        child: Scaffold(
          appBar: AppBar(
            automaticallyImplyLeading: false,
            actions: <Widget>[
              Padding(
                  padding: EdgeInsets.only(top: 10, right: 10),
                  child: Text(StringLiterals.ALARM_TEXT)),
              Padding(
                  padding: EdgeInsets.only(right: 15),
                  child: _BuildSwitch(bloc:  alarmBlocProvider))
            ],
            title: Text(StringLiterals.PAGE_TITLE_ALARM),
            bottom: MyTabBar(),
          ),
          body: TabBarView(
            children: <Widget>[
              _ListPage(StringLiterals.PRESENT, personBlocProvider),
              _ListPage(StringLiterals.SAFE, personBlocProvider),
              _ListPage(StringLiterals.UNKNOWN, personBlocProvider),
              _ListPage(StringLiterals.HOLIDAY, personBlocProvider),
            ],
          ),
        ),
    );
    }
}

这行得通,但应用程序一启动就会产生 BLoC,我意识到我不想要那样。

所以我决定将 BlocProviders 从 main 移动到我的视图文件中。

我的主变成了

              return MaterialApp(
                  title: 'Hat Mobile',
                  theme: ThemeData(
                    primarySwatch: Colors.green,
                  ),
                  home: LoginScreen(),
                );

并查看:

class AlarmView extends StatelessWidget {
  Widget build(BuildContext context) {
    final personBlocProvider = PersonBlocProvider.of(context);
    final alarmBlocProvider = AlarmBlocProvider.of(context);

    return PersonBlocProvider(
        personBloc: PersonBloc(BlueApiMock()),
        child: AlarmBlocProvider(
            alarmBloc: AlarmBloc(BlueApiMock()),
            child: DefaultTabController(
              length: 4,
              child: Scaffold(
                appBar: AppBar(
                  automaticallyImplyLeading: false,
                  actions: <Widget>[
                    Padding(
                        padding: EdgeInsets.only(top: 10, right: 10),
                        child: Text(StringLiterals.ALARM_TEXT)),
                    Padding(
                        padding: EdgeInsets.only(right: 15),
                        child: _BuildSwitch(bloc: alarmBlocProvider))
//                  child: _BuildSwitch(bloc:  AlarmBloc(BlueApiMock())))
                  ],
                  title: Text(StringLiterals.PAGE_TITLE_ALARM),
                  bottom: MyTabBar(),
                ),
                body: TabBarView(
                  children: <Widget>[
                    _ListPage(StringLiterals.PRESENT, personBlocProvider),
                    _ListPage(StringLiterals.SAFE, personBlocProvider),
                    _ListPage(StringLiterals.UNKNOWN, personBlocProvider),
                    _ListPage(StringLiterals.HOLIDAY, personBlocProvider),
                  ],
                ),
              ),
            )
        ));
  }
}

但是现在这会导致错误:

I/flutter ( 6448): The following NoSuchMethodError was thrown building AlarmView(dirty):
I/flutter ( 6448): The getter 'personBloc' was called on null.
I/flutter ( 6448): Receiver: null
I/flutter ( 6448): Tried calling: personBloc
I/flutter ( 6448): 
I/flutter ( 6448): When the exception was thrown, this was the stack:
I/flutter ( 6448): #0      Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 6448): #1      PersonBlocProvider.of (package:red_photon/alarm/providers/person_bloc_provider.dart:14:30)
I/flutter ( 6448): #2      AlarmView.build (package:red_photon/alarm/views/alarm_view.dart:17:51)

为什么现在为空?

【问题讨论】:

    标签: dart flutter bloc


    【解决方案1】:

    是的,您不能这样做,因为您传递的 context 不会有任何 bloc 祖先,而是尝试将 DefaultTabController 包装在 Builder 小部件中并使用该上下文(它将 bloc 作为祖先小部件树)。

    例子:

    class AlarmView extends StatelessWidget {
      Widget build(BuildContext context) {
        return PersonBlocProvider(
          personBloc: PersonBloc(BlueApiMock()),
          child: AlarmBlocProvider(
            alarmBloc: AlarmBloc(BlueApiMock()),
            child: Builder(
              builder: (context) {
                final personBlocProvider = PersonBlocProvider.of(context);
                final alarmBlocProvider = AlarmBlocProvider.of(context);
    
                return DefaultTabController(
                  length: 4,
                  child: Scaffold(
                    appBar: AppBar(
                      automaticallyImplyLeading: false,
                      actions: <Widget>[
                        Padding(
                            padding: EdgeInsets.only(top: 10, right: 10),
                            child: Text(StringLiterals.ALARM_TEXT)),
                        Padding(
                            padding: EdgeInsets.only(right: 15),
                            child: _BuildSwitch(bloc: alarmBlocProvider))
                        //                  child: _BuildSwitch(bloc:  AlarmBloc(BlueApiMock())))
                      ],
                      title: Text(StringLiterals.PAGE_TITLE_ALARM),
                      bottom: MyTabBar(),
                    ),
                    body: TabBarView(
                      children: <Widget>[
                        _ListPage(StringLiterals.PRESENT, personBlocProvider),
                        _ListPage(StringLiterals.SAFE, personBlocProvider),
                        _ListPage(StringLiterals.UNKNOWN, personBlocProvider),
                        _ListPage(StringLiterals.HOLIDAY, personBlocProvider),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        );
      }
    }
    

    这应该可行。

    希望对你有帮助!

    【讨论】:

    • 我不完全明白为什么,我认为来自Widget build(BuildContext context) { 的上下文就足够了。谢谢,它有效!我自己永远也找不到那个解决方案,非常感谢。
    • 完美解决方案...您是如何找到的?我已经反复遇到这个问题,现在我可以重构这么多代码! - 谢谢
    猜你喜欢
    • 2019-11-13
    • 2019-09-23
    • 2021-07-12
    • 2019-03-31
    • 1970-01-01
    • 2021-08-12
    • 2021-12-21
    • 2020-01-10
    • 2020-10-24
    相关资源
    最近更新 更多