Flutter 如何管理颤振应用程序中的选项卡

Flutter 如何管理颤振应用程序中的选项卡,flutter,dart,Flutter,Dart,我的应用程序中有3个选项卡,并且有一个日期选择器,每当我选择日期(从哪个选项卡开始)时,所有选项卡的日期都是相同的。3个选项卡中的所有数据都将根据选择的日期进行更改,为此提供了许多API。 但问题是每次我切换选项卡时,所有API都会再次命中。那么,我如何管理选项卡,使其在切换时不会命中API,直到我再次选择日期 class HomePage extends StatefulWidget { @override _HomePageState createState() => _

我的应用程序中有3个选项卡,并且有一个日期选择器,每当我选择日期(从哪个选项卡开始)时,所有选项卡的日期都是相同的。3个选项卡中的所有数据都将根据选择的日期进行更改,为此提供了许多API。 但问题是每次我切换选项卡时,所有API都会再次命中。那么,我如何管理选项卡,使其在切换时不会命中API,直到我再次选择日期

class HomePage extends StatefulWidget {
 

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  SelectedDates _selectedDates = SelectedDates();
  List<DateTime> selectedDates = List();
  int _currentIndex = 0;
  List<Widget> _children = [
    FirstPage(),
    ChartPage(),
    ActionPage(),
  ];

  onTabSelected(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    final _homeProvider = Provider.of<HomeProvider>(context);
    final _chartProvider = Provider.of<ChartListingProvider>(context);
    final _actionProvider = Provider.of<ActionProvider>(context);
    showDatePickerDialog(BuildContext context) async {
      final List<DateTime> picked = await DateRagePicker.showDatePicker(
        context: context,
        initialFirstDate: DateTime.now(),
        firstDate: DateTime(2015),
        initialLastDate: (DateTime.now()).add(
          Duration(days: 7),
        ),
        lastDate: DateTime(2025),
      );
      if (picked != null && picked.length == 2 && picked != selectedDates) {
        setState(() {
          selectedDates = picked;
          var formatter = DateFormat('dd/MM/yyyy');
          _selectedDates?.fromDate = formatter.format(picked[0]);
          _selectedDates?.endDate = formatter.format(picked[1]);

             _actionProvider.setDate(_selectedDates);

          _chartProvider.setDate(_selectedDates);

          _homeProvider.setDate(_selectedDates);
         
        });
      }
    }

    return ValueListenableBuilder(
      valueListenable: Hive.box(userDetailsBox).listenable(),
      builder: (_, Box box, __) {
        String token = box.get(authTokenBoxKey);
        String id = box.get(companyIdBoxKey);
        
         _actionProvider.setTokenAndCompanyId(token, id);
         //in the above function i have provided the apis related to third tab
        _chartProvider.setTokenAndCompanyId(token, id);
        //in the above function i have provided the apis related to second tab
        __homeProvider.setTokenAndCompanyId(token, id);
         //in the above function i have provided the apis related to first tab
        
          return DefaultTabController(
            length: 3,
            initialIndex: 1,
            child: Scaffold(
              floatingActionButton: FloatingActionButton(
                onPressed: () {
                  showDatePickerDialog(context);
                },
                child: Icon(Icons.date_range),
                backgroundColor: Theme.of(context).accentColor,
              ),
              
              appBar: AppBar(title: Text("Tab Controller"), actions: <Widget>[]),
              bottomNavigationBar: BottomNavigationBar(
                onTap: onTabSelected,
                items: [
                  BottomNavigationBarItem(
                    icon: Icon(Icons.home),
                    title: Text("Home"),
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.list),
                    title: Text("Chart"),
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.redo),
                    title: Text("Action"),
                  ),
                ],
                currentIndex: _currentIndex,
              ),
              body: _children[_currentIndex],
            ),
          );
       
      },
    );
  }
}
 
类主页扩展StatefulWidget{
@凌驾
_HomePageState createState()=>\u HomePageState();
}
类_HomePageState扩展状态{
SelectedDates _SelectedDates=SelectedDates();
列出所选日期=列表();
int _currentIndex=0;
列表_子项=[
首页(),
ChartPage(),
ActionPage(),
];
ontabs(整数索引){
设置状态(){
_currentIndex=索引;
});
}
@凌驾
小部件构建(构建上下文){
final _homeProvider=Provider.of(上下文);
final _chartProvider=Provider.of(上下文);
final _actionProvider=提供者(上下文);
showDatePickerDialog(构建上下文)异步{
最终选中列表=等待DateRagePicker.showDatePicker(
上下文:上下文,
initialFirstDate:DateTime.now(),
firstDate:DateTime(2015年),
initialLastDate:(DateTime.now()).add(
持续时间(天:7),
),
最后日期:日期时间(2025年),
);
如果(已拾取!=null&&picked.length==2&&picked!=selectedDates){
设置状态(){
选择的日期=选择的日期;
var formatter=DateFormat('dd/MM/yyyy');
_selectedDates?.fromDate=formatter.format(拾取[0]);
_selectedDates?.endDate=formatter.format(拾取[1]);
_actionProvider.setDate(_selectedDates);
_chartProvider.setDate(_selectedDates);
_homeProvider.setDate(_selectedDates);
});
}
}
返回值ListenableBuilder(
valueListenable:Hive.box(userDetailsBox.listenable(),
建筑商:(uu,Box,uuu){
字符串标记=box.get(authTokenBoxKey);
字符串id=box.get(companyIdBoxKey);
_actionProvider.setTokenAndCompanyId(令牌,id);
//在上面的函数中,我提供了与第三个选项卡相关的API
_setTokenAndCompanyId(令牌,id);
//在上面的函数中,我提供了与第二个选项卡相关的API
__homeProvider.setTokenAndCompanyId(令牌,id);
//在上面的函数中,我提供了与第一个选项卡相关的API
返回DefaultTabController(
长度:3,
初始索引:1,
孩子:脚手架(
浮动操作按钮:浮动操作按钮(
已按下:(){
showDatePickerDialog(上下文);
},
子:图标(图标。日期范围),
背景色:主题。背景色,
),
appBar:appBar(标题:文本(“选项卡控制器”),操作:[]),
底部导航栏:底部导航栏(
onTap:onTap当选,
项目:[
底部导航气压计(
图标:图标(Icons.home),
标题:文本(“主页”),
),
底部导航气压计(
图标:图标(Icons.list),
标题:文本(“图表”),
),
底部导航气压计(
图标:图标(Icons.redo),
标题:文本(“行动”),
),
],
currentIndex:_currentIndex,
),
正文:_children[_currentIndex],
),
);
},
);
}
}

这是因为
设置状态
迫使整个小部件重新构建

onTabSelected(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
在这种情况下,您可以使用提供者或其他状态管理库,例如,或其他任何东西

这些状态管理库允许您访问状态并通知更改,而无需重建整个树。有很多概念你可以通过谷歌来探索

实施 这是一个使用提供程序包的示例实现: 导航通知程序:

import 'package:flutter/material.dart';

class NavigationNotifier with ChangeNotifier {
  int _currentIndex = 0;

  get currentIndex => _currentIndex;

  set currentIndex(int index) {
    _currentIndex = index;
    notifyListeners();
  }
}
您的主文件/主页,无论是什么:

class Home extends StatelessWidget {
  final List<Widget> _children = [Screen1(), Screen2()];

  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<NavigationNotifier>(context);
...
bottomNavigationBar: BottomNavigationBar(
                onTap: (index) {
                  provider.currentIndex = index;
                },
                currentIndex: provider.currentIndex,
                showSelectedLabels: true,
                showUnselectedLabels: true,
                items: [
                  BottomNavigationBarItem(
                      icon: new Icon(Icons.home), label: 'home'),
                  BottomNavigationBarItem(
                      icon: new Icon(Icons.supervised_user_circle_outlined),
                      label: 'Profile')
                ],
              ),
              body: _children[provider.currentIndex]),
class Home扩展了无状态小部件{
最终列表_children=[Screen1(),Screen2()];
@凌驾
小部件构建(构建上下文){
var provider=provider.of(上下文);
...
底部导航栏:底部导航栏(
onTap:(索引){
provider.currentIndex=索引;
},
currentIndex:provider.currentIndex,
showSelectedLabels:true,
showUnselectedLabels:true,
项目:[
底部导航气压计(
图标:新图标(Icons.home),标签:“home”,
底部导航气压计(
图标:新图标(图标。受监督的\u用户\u圆圈\u轮廓),
标签:“配置文件”)
],
),
正文:_子项[provider.currentIndex]),

谢谢您的回复,Marcel Dz爵士。如您所述,我明白了您的观点,并向提供商进行了实施,但索引更改仍然存在问题,它再次从build()重新编译。请帮助解决此问题您是否删除了每个设置状态?是的,我删除了该设置状态,但它不起作用,然后尝试在正文中使用索引堆栈实现:IndexedStack(索引:_provider.currentIndex,子项:[FirstPage(),ChartPage(),ActionPage(),])那也不管用我遵循了这一点但不管用