BLoC 发射器未在 UI 中更新状态

huangapple go评论57阅读模式
英文:

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&#39;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&lt;StatefulWidget&gt; createState() =&gt; _BuildingState();
    }
    
    class _BuildingState extends State&lt;Buildings&gt; {
      late TextEditingController _searchController;
      late NearbybuildingsBloc nearbybuildingsBloc;
      late AllbuildingsBloc allbuildingsBloc;
      late String _searchText=&#39;&#39;;
      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&lt;NearbybuildingsBloc&gt;(create: (context) =&gt; nearbybuildingsBloc..add(NearbyBuildings())),
            BlocProvider&lt;AllbuildingsBloc&gt;(create: (context) =&gt; 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: () =&gt; _searchController.clear(),
                    ),
                    isDense: true,
                    hintText: &#39;Building name&#39;,
                    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: &#39;&#39;,
                  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: &#39;&#39;,
                    iconData: Icons.help,
                    notificationCount: 1,
                    onTap: () {
                    },
                  )],
                bottom:
                _searchText.isEmpty? TabBar(
                  tabs: [
                    Tab(text: &#39;Near by&#39;),
                    Tab(text: &#39;All Buildings&#39;)
                  ],
                ):null,
              ),
              body:  _searchText.isEmpty?TabBarView(
                children: [
                  // Nearby buildings
                  BlocBuilder&lt;NearbybuildingsBloc, NearbybuildingsState&gt;(
                    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(&quot;Showing ${state.nearBuildingList.length.toString()} buildings &quot;, style: const TextStyle(
                                fontSize: 13,
    
                                color: AppColor.bt_indigo,
                                fontFamily: &#39;BT Regular&#39;),
                            ),
                            Expanded(
                              child: ListView.builder(
                                  itemCount: state.nearBuildingList.length,
                                  itemBuilder: (BuildContext context, int position) {
                                    return row.getRow(state.nearBuildingList[position], context);
                                  }),
                            )
                          ],
                        );
                      }
    
                      return const Text(&quot;Failed to load buildings&quot;);
                    },
                  ),
    
                  // All buildings
                  BlocBuilder&lt;AllbuildingsBloc, AllbuildingsState&gt;(
                    builder: (context, state) {
    
                      if( state is AllbuildingsError){
                        return const Text(&quot;Failed to load buildings&quot;);
                      }
    
                      if (state is AllbuildingsLoaded) {
                        return  Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: [
                            Text(&quot;Showing ${state.all.length.toString()} buildings &quot;, style: const TextStyle(
                                fontSize: 13,
                                color: AppColor.bt_indigo,
                                fontFamily: &#39;BT Regular&#39;),
                            ),
                            Expanded(
                              child: ListView.builder(
                                  itemCount: state.all.length,
                                  itemBuilder: (BuildContext context, int position) {
                                    return row.getRow(state.all[position], context);
                                  }),
                            )
                          ],
                        );
                      }
                      return const Text(&quot;Failed to load buildings&quot;);
                    },
                  ),
                ],
              ):
    
                  // All buildings
                  BlocBuilder&lt;AllbuildingsBloc, AllbuildingsState&gt;(
                    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(&quot;Showing ${state.searchresults.length.toString()} buildings &quot;, style: const TextStyle(
                                fontSize: 13,
                                color: AppColor.bt_indigo,
                                fontFamily: &#39;BT Regular&#39;),
                            ),
                            Expanded(
                              child: ListView.builder(
                                  itemCount: state.searchresults.length,
                                  itemBuilder: (BuildContext context, int position) {
                                    return row.getRow(state.searchresults[position], context);
                                  }),
                            )
                          ],
                        );
                      }
                      return const Text(&quot;Failed to load buildings&quot;);
                    },
                  ),
    
    
              // This trailing comma makes auto-formatting nicer for build methods.
            ),
          ),
        );
      }
    }
 

**State**

    class SearchBuildingLoadedState extends AllbuildingsState{
    
      List&lt;Building&gt; searchresults;
      SearchBuildingLoadedState({required this.searchresults});
    
      @override
      List&lt;Object&gt; get props {
        return [searchresults];
      }
    }

**Event**

    class SearchbuildingLoadingEvent extends AllbuildingsEvent {
    
      final String query;
    
      SearchbuildingLoadingEvent({required this.query});
      @override
      List&lt;Object&gt; get props {
        return [query];
      }
    }

**BLoC**

    class AllbuildingsBloc extends Bloc&lt;AllbuildingsEvent, AllbuildingsState&gt; {
      AllbuildingsBloc() : super(AllbuildingsInitial()) {
        on&lt;SearchbuildingLoadingEvent&gt;(_onSearchBuilding);
      }
    
      Future&lt;void&gt; _onSearchBuilding(SearchbuildingLoadingEvent event, Emitter&lt;AllbuildingsState&gt; emit) async {
        emit(SearchbuildingLoadingState());
        if(event.query.isNotEmpty || event.query.isNotEmpty) {
          final database = await $FloorAppDataBase
              .databaseBuilder(&#39;bootcamp-instagram-project.db&#39;)
              .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: &#39;Near by&#39;),
Tab(text: &#39;All Buildings&#39;)
],
)

huangapple
  • 本文由 发表于 2023年2月10日 10:26:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75406376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定