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