在我的项目中,我使用带有自定义提供程序的架构。
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider(
{@required this.child,
@required this.bloc,
@required this.blocContext,
Key key})
: super(key: key);
final T bloc;
final Widget child;
final BlocContextBase<T> blocContext;
@override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context) {
final BlocProvider<T> provider = context.findAncestorWidgetOfExactType();
return provider.bloc;
}
}
class _BlocProviderState<T> extends State<BlocProvider<BlocBase>> {
@override
void initState() {
super.initState();
widget.blocContext.subscribe(widget.bloc, context);
}
@override
void dispose() {
widget.bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
一切正常,直到我切换到 BottomNavigationBar。
class TabContainerContent {
final Widget firstTab;
final Widget secondTab;
final Widget thirdTab;
TabContainerContent(
{@required this.firstTab,
@required this.secondTab,
@required this.thirdTab});
}
class TabContainerScreen extends StatefulWidget {
final TabContainerContent _content;
TabContainerScreen({@required TabContainerContent content})
: _content = content;
@override
_TabContainerScreenState createState() => _TabContainerScreenState();
}
class _TabContainerScreenState extends State<TabContainerScreen> {
int _selectedIndex = 0;
List<BottomNavigationBarItem> _bottomBarItems = [];
List<Widget> _tabWidgets = [];
@override
void initState() {
super.initState();
_tabWidgets.add(widget._content.firstTab);
_bottomBarItems.add(
BottomNavigationBarItem(
icon: Icon(Icons.map),
label: 'Profile',
),
);
_tabWidgets.add(widget._content.secondTab);
_bottomBarItems.add(
BottomNavigationBarItem(
icon: Icon(Icons.location_city),
label: 'Search',
),
);
_tabWidgets.add(widget._content.thirdTab);
_bottomBarItems.add(
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit),
label: 'Ads',
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _tabWidgets[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: _bottomBarItems,
currentIndex: _selectedIndex,
onTap: (int value) {
setState(() {
_selectedIndex = value;
});
},
),
);
}
}
只有当集团在我的集团中有一个流控制器并且我在我的小部件中使用 StreamBuilder 时,问题才会开始。 如果我转到另一个选项卡然后返回。然后我收到错误 Stream 已经被监听。 在我看来,我并没有在某处删除某些数据。
这就是集团的样子。
class ProfileBloc extends IProfileBloc {
final StreamController<User> _userControllerOne = StreamController<User>();
Sink<User> get _inUserState => _userControllerOne.sink;
Stream<User> get outUserState => _userControllerOne.stream;
@override
void dispose() {
_userControllerOne.close();
super.dispose();
}
}
--
class SearchBloc extends ISearchBloc {
final StreamController<User> _userControllerTwo = StreamController<User>();
Sink<User> get _inUserState => _userControllerTwo.sink;
Stream<User> get outUserState => _userControllerTwo.stream;
@override
void dispose() {
_userControllerTwo.close();
super.dispose();
}
}
--
class AdsBloc extends IAdsBloc {
final StreamController<User> _userControllerThree = StreamController<User>();
Sink<User> get _inUserState => _userControllerThree.sink;
Stream<User> get outUserState => _userControllerThree.stream;
@override
void dispose() {
_userControllerThree.close();
super.dispose();
}
}
这就是我的用户界面的样子
class ProfileScreen extends StatefulWidget {
ProfileScreen({Key key}) : super(key: key);
@override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
IProfileBloc _bloc;
@override
void initState() {
super.initState();
_bloc = BlocProvider.of(context);
_bloc.loadUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: StreamBuilder(
stream: _bloc.outUserState,
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
return Container();
},
),
));
}
}
--
class SearchScreen extends StatefulWidget {
SearchScreen({Key key}) : super(key: key);
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
ISearchBloc _bloc;
@override
void initState() {
super.initState();
_bloc = BlocProvider.of(context);
_bloc.loadUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: StreamBuilder(
stream: _bloc.outUserState,
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
return Container();
},
),
));
}
}
--
class AdsScreen extends StatefulWidget {
AdsScreen({Key key}) : super(key: key);
@override
_AdsScreenState createState() => _AdsScreenState();
}
class _AdsScreenState extends State<AdsScreen> {
IAdsBloc _bloc;
@override
void initState() {
super.initState();
_bloc = BlocProvider.of(context);
_bloc.loadUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: StreamBuilder(
stream: _bloc.outUserState,
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
return Container();
},
),
));
}
}
我也使用注射器。
class ApplicationAssembly {
static final Injector injector = Injector('ApplicationAssemblyInjector');
//----------------------------------------------------------------------------
static void initialize() {
_registerManagers();
_registerBlocs();
_registerModuleBuilders();
}
static void _registerManagers() {
}
static void _registerBlocs() {
injector.map<IProfileBloc>((i) => ProfileBloc());
injector.map<IAdsBloc>((i) => AdsBloc());
injector.map<ISearchBloc>((i) => SearchBloc());
}
static void _registerModuleBuilders() {
//TAB BAR MODULES---------------------------------------------------------------
injector.map<ProfileModuleBuilder>((i) => () {
return BlocProvider(
child: ProfileScreen(),
bloc: i.get<IProfileBloc>(),
blocContext: ProfileBlocContext());
});
injector.map<SearchModuleBuilder>((i) => () {
return BlocProvider(
child: SearchScreen(),
bloc: i.get<ISearchBloc>(),
blocContext: SearchBlocContext());
});
injector.map<AdsModuleBuilder>((i) => () {
return BlocProvider(
child: AdsScreen(),
bloc: i.get<IAdsBloc>(),
blocContext: AdsBlocContext());
});
//------------------------------------------------------------------------------
//TAB BAR-----------------------------------------------------------------------
injector.map<TabModuleBuilder>((i) => () {
Widget profileTab = i.get<ProfileModuleBuilder>()();
Widget searchTab = i.get<SearchModuleBuilder>()();
Widget adsTab = i.get<AdsModuleBuilder>()();
return TabContainerScreen(
content: TabContainerContent(
firstTab: profileTab, secondTab: searchTab, thirdTab: adsTab),
);
});
//------------------------------------------------------------------------------
}
}
答案 0 :(得分:0)
我在我的项目中遇到了同样的错误。
就我而言,我需要重新使用 StreamController。 场景是,有重置按钮从头开始搜索信息。
反正我是这样解决的。
.close()
以重置按钮。 if (streamController.isCloded) {
streamController = new StreamController<List<A>>();
}
在您的情况下,我认为 tabview 会重新生成(或重新构建?)视图。 所以StreamController重新初始化。
我认为您会在 initState 中添加初始化 StreamContrller。
@override
void initState(){
super.initState();
if (streamController == null){
streamController = new StreamController();
}
希望对你有帮助。