为什么这个 bloc getter 在 null 上被调用?
Why is this bloc getter called on null?
之前我在 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 从主文件移动到我的视图文件。
我的主力变成了
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)
为什么现在为空?
是的,你不能这样做,因为你传递的 context
没有任何 bloc 祖先,而是尝试将 DefaultTabController
包装在 Builder
小部件中并使用该上下文(它将把 bloc 作为 widget 树中的祖先。
示例:
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),
],
),
),
);
},
),
),
);
}
}
这应该有效。
希望对您有所帮助!
之前我在 main.dart
中初始化我的 PersonBlocProviderreturn 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 从主文件移动到我的视图文件。
我的主力变成了
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)
为什么现在为空?
是的,你不能这样做,因为你传递的 context
没有任何 bloc 祖先,而是尝试将 DefaultTabController
包装在 Builder
小部件中并使用该上下文(它将把 bloc 作为 widget 树中的祖先。
示例:
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),
],
),
),
);
},
),
),
);
}
}
这应该有效。
希望对您有所帮助!