英文:
BLoC emit not updating the state in UI
问题
我已经构建了具有Appbar、Tabs和TabView的屏幕,Appear具有TextField,每次文本更改时,控件都会进入BLoC的发射,但从未在UI接收到。请查看以下代码,感谢您的任何帮助。
class Buildings extends StatefulWidget {
const Buildings({super.key});
@override
State<StatefulWidget> createState() => _BuildingState();
}
class _BuildingState extends State<Buildings> {
late TextEditingController _searchController;
late NearbybuildingsBloc nearbybuildingsBloc;
late AllbuildingsBloc allbuildingsBloc;
late String _searchText = '';
late BuildContext allBuildingContext;
@override
void initState() {
nearbybuildingsBloc = NearbybuildingsBloc();
allbuildingsBloc = AllbuildingsBloc();
_searchController = TextEditingController();
_searchController.addListener(() {
_searchText = _searchController.text;
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<NearbybuildingsBloc>(
create: (context) => nearbybuildingsBloc..add(NearbyBuildings())),
BlocProvider<AllbuildingsBloc>(
create: (context) => allbuildingsBloc..add(AllBuildings()))
],
child: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: AppColor.bt_indigo,
title: TextField(
onChanged: (value) {
allbuildingsBloc.add(
SearchbuildingLoadingEvent(query: _searchText),
);
},
style: const TextStyle(color: Colors.white),
controller: _searchController,
decoration: InputDecoration(
suffixIcon: _searchText.isEmpty
? null
: IconButton(
icon: const Icon(Icons.clear),
color: Colors.white,
onPressed: () => _searchController.clear(),
),
isDense: true,
hintText: 'Building name',
hintStyle: const TextStyle(color: AppColor.border_color),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
width: 2, color: AppColor.text_editor_background),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(
width: 2, color: AppColor.text_editor_background),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
fillColor: AppColor.text_editor_background,
),
),
actions: [
NamedIcon(
text: '',
iconData: Icons.filter_list_alt,
onTap: () {
/*showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext buildContext) {
return StatefulBuilder(
builder: (buildContext, state) {
return _openFilterCategoryDialog(
filterCategories, context, state);
});
});*/
},
),
NamedIcon(
text: '',
iconData: Icons.help,
notificationCount: 1,
onTap: () {},
)
],
bottom: _searchText.isEmpty
? TabBar(
tabs: [
Tab(text: 'Near by'),
Tab(text: 'All Buildings')
],
)
: null,
),
body: _searchText.isEmpty
? TabBarView(
children: [
// Nearby buildings
BlocBuilder<NearbybuildingsBloc, NearbybuildingsState>(
builder: (context, state) {
if (state is NearbybuildingsLoading) {
return const Center(
child: CircularProgressIndicator(
color: AppColor.bt_indigo,
),
);
}
if (state is NearbybuildingsGpsPerm) {
return row.getGPS(context);
}
if (state is NearbybuildingsLoaded) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Showing ${state.nearBuildingList.length.toString()} buildings ",
style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.nearBuildingList.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.nearBuildingList[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
// All buildings
BlocBuilder<AllbuildingsBloc, AllbuildingsState>(
builder: (context, state) {
if (state is AllbuildingsError) {
return const Text("Failed to load buildings");
}
if (state is AllbuildingsLoaded) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Showing ${state.all.length.toString()} buildings ",
style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.all.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.all[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
],
)
:
// All buildings
BlocBuilder<AllbuildingsBloc, AllbuildingsState>(
builder: (context, state) {
if (state is SearchbuildingLoadingState) {
return const Center(
child: CircularProgressIndicator(
color: AppColor.bt_indigo,
),
);
}
if (state is SearchBuildingLoadedState) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Showing ${state.searchresults.length.toString()} buildings ",
style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.searchresults.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.searchresults[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
),
),
);
}
}
State
class SearchBuildingLoadedState extends AllbuildingsState {
List<Building> searchresults;
SearchBuildingLoadedState({required this.searchresults});
@override
List<Object> get props {
return [searchresults];
}
}
Event
class SearchbuildingLoadingEvent extends AllbuildingsEvent {
final String query;
SearchbuildingLoadingEvent({required this.query});
@override
List<Object> get props {
return [query];
}
}
BLoC
class AllbuildingsBloc extends Bloc<AllbuildingsEvent, AllbuildingsState> {
AllbuildingsBloc() : super(AllbuildingsInitial()) {
on<SearchbuildingLoadingEvent>(_onSearchBuilding);
}
Future<void>
<details>
<summary>英文:</summary>
I have build the screen with Appbar,Tabs and TabView, the Appear has TextField, every time text changes, the control is going inside the BLoC's emit but never received at UI. Please find the code below, I appreciate your any help.
class Buildings extends StatefulWidget {
const Buildings({super.key});
@override
State<StatefulWidget> createState() => _BuildingState();
}
class _BuildingState extends State<Buildings> {
late TextEditingController _searchController;
late NearbybuildingsBloc nearbybuildingsBloc;
late AllbuildingsBloc allbuildingsBloc;
late String _searchText='';
late BuildContext allBuildingContext;
@override
void initState() {
nearbybuildingsBloc = NearbybuildingsBloc();
allbuildingsBloc = AllbuildingsBloc();
_searchController = TextEditingController();
_searchController.addListener(() {
_searchText = _searchController.text;
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<NearbybuildingsBloc>(create: (context) => nearbybuildingsBloc..add(NearbyBuildings())),
BlocProvider<AllbuildingsBloc>(create: (context) => allbuildingsBloc..add(AllBuildings()))
],
child: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: AppColor.bt_indigo,
title: TextField(
onChanged: (value) {
allbuildingsBloc.add(
SearchbuildingLoadingEvent(query: _searchText),
);
},
style: const TextStyle(color: Colors.white),
controller: _searchController,
decoration: InputDecoration(
suffixIcon: _searchText.isEmpty
? null
:IconButton(
icon: const Icon(Icons.clear),
color: Colors.white,
onPressed: () => _searchController.clear(),
),
isDense: true,
hintText: 'Building name',
hintStyle: const TextStyle(color: AppColor.border_color),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: AppColor.text_editor_background),
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(
width: 2,
color: AppColor.text_editor_background),
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
),
fillColor: AppColor.text_editor_background,),
),
actions: [
NamedIcon(
text: '',
iconData: Icons.filter_list_alt,
onTap: () {
/*showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext buildContext) {
return StatefulBuilder(
builder: (buildContext, state) {
return _openFilterCategoryDialog(
filterCategories, context, state);
});
});*/
},
),
NamedIcon(
text: '',
iconData: Icons.help,
notificationCount: 1,
onTap: () {
},
)],
bottom:
_searchText.isEmpty? TabBar(
tabs: [
Tab(text: 'Near by'),
Tab(text: 'All Buildings')
],
):null,
),
body: _searchText.isEmpty?TabBarView(
children: [
// Nearby buildings
BlocBuilder<NearbybuildingsBloc, NearbybuildingsState>(
builder: (context, state) {
if( state is NearbybuildingsLoading){
return const Center(child: CircularProgressIndicator(
color: AppColor.bt_indigo,
));
}
if(state is NearbybuildingsGpsPerm){
return row.getGPS(context);
}
if (state is NearbybuildingsLoaded) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Showing ${state.nearBuildingList.length.toString()} buildings ", style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.nearBuildingList.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.nearBuildingList[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
// All buildings
BlocBuilder<AllbuildingsBloc, AllbuildingsState>(
builder: (context, state) {
if( state is AllbuildingsError){
return const Text("Failed to load buildings");
}
if (state is AllbuildingsLoaded) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Showing ${state.all.length.toString()} buildings ", style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.all.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.all[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
],
):
// All buildings
BlocBuilder<AllbuildingsBloc, AllbuildingsState>(
builder: (context, state) {
if( state is SearchbuildingLoadingState){
return const Center(child: CircularProgressIndicator(
color: AppColor.bt_indigo,
));
}
if (state is SearchBuildingLoadedState) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Showing ${state.searchresults.length.toString()} buildings ", style: const TextStyle(
fontSize: 13,
color: AppColor.bt_indigo,
fontFamily: 'BT Regular'),
),
Expanded(
child: ListView.builder(
itemCount: state.searchresults.length,
itemBuilder: (BuildContext context, int position) {
return row.getRow(state.searchresults[position], context);
}),
)
],
);
}
return const Text("Failed to load buildings");
},
),
// This trailing comma makes auto-formatting nicer for build methods.
),
),
);
}
}
**State**
class SearchBuildingLoadedState extends AllbuildingsState{
List<Building> searchresults;
SearchBuildingLoadedState({required this.searchresults});
@override
List<Object> get props {
return [searchresults];
}
}
**Event**
class SearchbuildingLoadingEvent extends AllbuildingsEvent {
final String query;
SearchbuildingLoadingEvent({required this.query});
@override
List<Object> get props {
return [query];
}
}
**BLoC**
class AllbuildingsBloc extends Bloc<AllbuildingsEvent, AllbuildingsState> {
AllbuildingsBloc() : super(AllbuildingsInitial()) {
on<SearchbuildingLoadingEvent>(_onSearchBuilding);
}
Future<void> _onSearchBuilding(SearchbuildingLoadingEvent event, Emitter<AllbuildingsState> emit) async {
emit(SearchbuildingLoadingState());
if(event.query.isNotEmpty || event.query.isNotEmpty) {
final database = await $FloorAppDataBase
.databaseBuilder('bootcamp-instagram-project.db')
.build();
final buildingDao = database.buildingDao;
var getBuilding = await buildingDao.getSearchBuildings(
event.query);
if (getBuilding != null) {
emit(SearchBuildingLoadedState(searchresults: getBuilding));
} else {
emit(SearchbuildingNoDataState());
}
}else{
emit(SearchbuildingNoDataState());
}
}
}
</details>
# 答案1
**得分**: 1
请检查标签栏视图,其中应该有三个Bloc构建器,您提供的地方,
您是否可以尝试更改标签控制器
```dart
DefaultTabController(
length: 3,
child: Scaffold(
并在此添加一个额外的选项卡栏
TabBar(
tabs: [
Tab(text: 'Near by'),
Tab(text: 'All Buildings')
],
)
英文:
Please check the tab bar view to have three bloc builders where you provided,
whether you can try with
changing the tab controller
DefaultTabController(
length: 3,
child: Scaffold(
and add 1 more tabbar here
TabBar(
tabs: [
Tab(text: 'Near by'),
Tab(text: 'All Buildings')
],
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论