为什么将这个bloc getter调用为null?

时间:2019-04-23 14:25:16

标签: dart flutter bloc

以前,我是在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)

为什么现在为空?

2 个答案:

答案 0 :(得分:2)

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

示例:

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),
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

这应该有效。

希望有帮助!

答案 1 :(得分:0)

我在从抽屉导航到页面时遇到了同样的错误。下面是代码,但经过多次尝试找不到解决方案。

Navigator.push(context,MaterialPageRoute(builder: (context){
    final nbloc = BlocProvider.of<NotificationBloc>(context);
    return BlocProvider(child: NotificationPage(), bloc: nbloc);
}));