为什么我的页面在颤动时底部导航没有刷新?

问题描述

我正在使用颤动的底部导航栏。我想在切换选项卡时刷新每个选项卡。首先,我尝试为所有选项卡重用一个无状态小部件。但它正在重新渲染页面。我的代码如下:

extract(lst,3)
print(output)
>>> [1,2,3,4,5,6,7,8]

这是我的无状态小部件:

class _CreateOrderState extends State<CreateOrder> {
  int _currentTabIndex = 0;

  @override
  Widget build(BuildContext context) {
     final _kTabPages = <Widget>[
       FoodCategory(foodCategory: 'nationalFood'),FoodCategory(foodCategory: 'fastFood'),FoodCategory(foodCategory: 'dessert'),FoodCategory(foodCategory: 'drinks'),];

    final _kBottomNavBarItems = <BottomNavigationBarItem>[
      const BottomNavigationBarItem(
        icon: Icon(Icons.fastfood_outlined),label: 'Традиционная',),const BottomNavigationBarItem(
        icon: Icon(Icons.alarm),label: 'Фаст Фуд',const BottomNavigationBarItem(
        icon: Icon(Icons.food_bank_outlined),label: 'Дессерты',const BottomNavigationBarItem(
        icon: Icon(Icons.emoji_food_beverage),label: 'Напитки',];
    assert(_kTabPages.length == _kBottomNavBarItems.length);
    final bottomNavBar = BottomNavigationBar(
      items: _kBottomNavBarItems,currentIndex: _currentTabIndex,type: BottomNavigationBarType.fixed,onTap: (int index) {
        setState(() => _currentTabIndex = index);
      },);

    return WillPopScope(
      onWillPop: () => _onWillPop(),child: Scaffold(
        appBar: AppBar(
          title: const Text('Создание заказа'),backgroundColor: Theme.of(context).primaryColor,actions: [
            Container(
              child: Stack(
                children: [
                  IconButton(
                    icon: Icon(Icons.shopping_bag_outlined),onpressed: () =>
                        Navigator.pushNamed(context,'/orderReview'),iconSize: 30,],)
          ],body: _kTabPages[_currentTabIndex],// body: IndexedStack(
        //   index: _currentTabIndex,//   children: _kTabPages,// ),bottomNavigationBar: bottomNavBar,);
  }

但是当我为所有选项卡使用不同的小部件时,它开始正常工作并刷新。


import 'package:counter/blocs/food/food_bloc.dart';
import 'package:counter/data/repository/food_repository.dart';
import 'package:counter/presentation/widgets/Loading.dart';
import 'package:counter/presentation/widgets/MenuItem.dart';
import 'package:counter/presentation/widgets/network_error.dart';
import 'package:Flutter/cupertino.dart';
import 'package:Flutter/material.dart';
import 'package:Flutter_bloc/Flutter_bloc.dart';

class FoodCategory extends StatelessWidget {
  final String foodCategory;
  FoodCategory({@required this.foodCategory});

  @override
  Widget build(BuildContext context) {
    FoodRepository foodRepository = FoodRepository(category: this.foodCategory);

    return BlocProvider<FoodBloc>(
      create: (BuildContext context) =>
          FoodBloc(foodRepository: foodRepository)..add(FoodLoadEvent()),child: Scaffold(
        body: BlocBuilder<FoodBloc,FoodState>(
          builder: (context,state) {
            if (state is FoodInitial) {
              return Text('Initial state');
            }
            if (state is FoodLoadingState) {
              return Customloading();
            }
            if (state is FoodLoadedState) {
              return ListView.builder(
                itemBuilder: (BuildContext context,index) {
                  return MenuItem(foodItem: state.loadedFoodItems[index]);
                },itemCount: state.loadedFoodItems.length,);
            } else {
              return NetworkErrorWidget();
            }
          },);
  }
}

解决方法

initStateFoodCategory 小部件的 NationalFood 中,添加检索数据的函数。

,

由于您将 _kTabPages_kBottomNavBarItems 初始化放置在 build() 方法中,因此每次状态发生变化时(当您更改选项卡时),这些变量都会被赋予新值。这就是标签不断重新呈现的原因。

要阻止这种情况,请将您的初始化放在 initState() 中。像这样:

import 'package:flutter/material.dart';
import 'package:test_flutter_app/test.dart';

class CreateOrder extends StatefulWidget {
  @override
  _CreateOrderState createState() => _CreateOrderState();
}

class _CreateOrderState extends State<CreateOrder> {
  int _currentTabIndex = 0;
  List<Widget> _kTabPages;
  List<BottomNavigationBarItem> _kBottomNavBarItems;
  BottomNavigationBar bottomNavBar;

  _updateTabs() {
    _kTabPages = <Widget>[
      FoodCategory(key: UniqueKey(),foodCategory: 'nationalFood'),FoodCategory(key: UniqueKey(),foodCategory: 'fastFood'),foodCategory: 'dessert'),foodCategory: 'drinks'),];

    _kBottomNavBarItems = <BottomNavigationBarItem>[
      const BottomNavigationBarItem(
        icon: Icon(Icons.fastfood_outlined),label: 'Традиционная',),const BottomNavigationBarItem(
        icon: Icon(Icons.alarm),label: 'Фаст Фуд',const BottomNavigationBarItem(
        icon: Icon(Icons.food_bank_outlined),label: 'Дессерты',const BottomNavigationBarItem(
        icon: Icon(Icons.emoji_food_beverage),label: 'Напитки',];
    bottomNavBar = BottomNavigationBar(
      items: _kBottomNavBarItems,currentIndex: _currentTabIndex,type: BottomNavigationBarType.fixed,onTap: (int index) {
        setState(() => _currentTabIndex = index);
      },);
    assert(_kTabPages.length == _kBottomNavBarItems.length);
  }

  @override
  void initState() {
    _updateTabs();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => true,child: Scaffold(
        appBar: AppBar(
          title: const Text('Создание заказа'),backgroundColor: Theme.of(context).primaryColor,body: _kTabPages[_currentTabIndex],// body: IndexedStack(
        //   index: _currentTabIndex,//   children: _kTabPages,// ),bottomNavigationBar: bottomNavBar,);
  }
}