FutureBuilder在使用Flutter更改Tab时未解决问题



我的flutter应用程序有两个选项卡,'场景和'时间表。第一个选项卡是场景,第二个选项卡是时间表。每个选项卡都有自己的未来需要解决。在初始加载时,将解决选项卡场景对应的未来问题。但是,每当我将选项卡从场景切换到时间表时,与选项卡计划相关联的未来都不会得到解决。它既不抛出异常也不抛出数据。相反,显示与计划未来相对应的进度指示器,而不解决未来。

这是我迄今为止完成的代码

class Automation extends StatefulWidget {
final int selectedIndex;//Holding current tab index
Automation(this.selectedIndex);
@override
_AutomationState createState() => _AutomationState();
}
class _AutomationState extends State<Automation> {
TextEditingController _startTimeController = TextEditingController();
TextEditingController _endTimeController = TextEditingController();

int _currentIndex = 0;
late final List<Scene> _userScenes;
late List<Schedule> _userSchedules = [];
var _sceneFuture;  //Holding scene future
var _scheduleFeature; //Holding schedule future
late Size size; //Holding window size
// getting scene from database
_getScenes() async {
try {
final List<Scene> scenes =
await CommonMethods.getScenes(MyApp.currentUser.id, context);
_userScenes = scenes;          
return _userScenes;
} catch (e) {
print(e);
throw e;
}
}
// Getting schedule from database
_getSchedules() async {
try {
final schedules =
await CommonMethods.getSchedules(MyApp.currentUser.id, context);
print('Schedules list from _getSchedule : ' + schedules.toString());
_userSchedules = schedules;
return _userSchedules;
} catch (e) {
print(e);
throw e;
}
}
@override
void initState() {
super.initState();
print('Init state called with index $_currentIndex');
_startTimeController.clear();
_endTimeController.clear();
_sceneFuture = _getScenes();//on init state resolving only the _sceneFuture
}
@override
Widget build(BuildContext context) {

print('Build device of automation called');
size = MediaQuery.of(context).size;
return DefaultTabController(
initialIndex: widget.selectedIndex,
length: 2,
child: Scaffold(
appBar: AppBarWidget(
title: 'Automation',
fromPage: 'automation',
callback: this.callback,
selectedIndex: this._currentIndex,
addSceneCallBack: this.addSceneCallBack,
),
body: Padding(
padding: EdgeInsets.only(top: 10),
child: Column(
children: <Widget>[
Container(
height: 50,
margin:
const EdgeInsets.symmetric(horizontal: 40, vertical: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: const Color(0xffEEEEEE),
),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: TabBar(
unselectedLabelColor: Colors.black87,
onTap: _onTabTap,// function will trigger on tab change
labelStyle:
TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
indicator: BoxDecoration(
gradient: LinearGradient(colors: gradientColors),
borderRadius: BorderRadius.circular(10)),
tabs: [
const Tab(
text: 'Scenes',  //first tab
),
const Tab(
text: 'Schedules',  //second tab
)
],
),
),
),
Center(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
height: MediaQuery.of(context).size.height * 0.60,
child: TabBarView(
children: <Widget>[_buildScenes(),//building widget for first tab 'scene'
_buildSchedules() // building widget for second tab 'schedules',<--- here is the problem,The future associated with this method is not resolving when changing tab from 'scene' to 'schedule'
],
),
),
),
],
),
),
),
);
}
// method will trigger on tab change
_onTabTap(int index) {
print('Tab pressed with index : ' + index.toString());
setState(() {
this._currentIndex = index;
if (this._currentIndex == 1) _scheduleFeature = _getSchedules();//Trying to resolve _scheduleFuture
});
}
// building view for the tab 'scene'
Widget _buildScenes() {
final double height = size.height;
return FutureBuilder(
builder: (context, snapshot) {
if (snapshot.hasData) {
print('snap shot got data at scene build');
if (_userScenes.isEmpty)
return _buildEmptyWidget('Oops...scene list is empty!');
return Center(
child: ListView.builder(
itemCount: _userScenes.length,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onDoubleTap: () => _deleteSceneFromList(_userScenes[index]),
child: SimpleShadow(
color: const Color(0xffc0c0c0),
opacity: 0.7,
sigma: 6,
child: Container(
height: 360,
width: 240,
margin: const EdgeInsets.symmetric(
horizontal: 10, vertical: 20),
decoration: BoxDecoration(
color: MyApp.isDarkMode
? AppConstants.WHITE_COLOUR
: Colors.blueGrey,
borderRadius: BorderRadius.circular(10),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 50),
child: SimpleShadow(
color: const Color(0xffc0c0c0),
opacity: 0.7,
sigma: 4,
child: Image.asset(
_userScenes[index].imgUrl,
width: 75,
height: 75,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(
_userScenes[index].title,
style: TextStyle(
color: MyApp.isDarkMode
? AppConstants.DARK_COLOUR
: AppConstants.WHITE_COLOUR,
fontSize: 20,
fontWeight: FontWeight.w600,
fontFamily: 'Poppins'),
),
),
Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
_userScenes[index].deviceList.length.toString() +
' devices',
style: TextStyle(
// color: darkGreyColor,
color: MyApp.isDarkMode
? darkGreyColor
: Colors.lightGreen,
fontSize: 16,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 30),
child: CustomButton(
text: _userScenes[index].isActivated
? 'Activated'
: 'Activate',
onPressed: () => Navigator.of(context).push(
MaterialPageRoute<Null>(
builder: (BuildContext context) {
return SceneDetailed(
selectedScene: _userScenes[index],
callback: this.callback,
addSceneCallBack: this.addSceneCallBack,
);
},
fullscreenDialog: true),
),
maxwidth: 120,
minheight: 45,
fontSize: 16,
),
)
],
),
),
),
);
},
),
);
} else if (snapshot.hasError) {
print('snapshot got error at scene build');
const String message = 'Failed to get scenes data!';
return _buildErrorWindow(height, message);
} else {
print('getting data at scene view');
return _buildSpinner(height);
}
},
future: _sceneFuture,
);
}
//building schedule widget for tab 'schedule'
//This will call for the second tab schedules
//This FutureBuilder is not getting resolved
//It statys always in the state 'loading',neither throwing exception nor future data
Widget _buildSchedules() {
print('current index from _buildSchedules $_currentIndex');
final height = size.height;
print('Getting actual schedule');
return FutureBuilder(
future: _scheduleFeature,
builder: (context, snapshot) {
if (snapshot.hasData) {
print('future builder got schedule data');
if (_userSchedules.isEmpty) {
print('at _buildSchedule and user list is empty;nothing to show!');
return _buildEmptyWidget('Oops...schedule list is empty!');
}
return ListView.builder(
itemCount: _userSchedules.length,
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: UniqueKey(),
background: Container(
height: 90,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.only(top: 20),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10)),
child: Padding(
padding: EdgeInsets.only(right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
'Delete',
style: TextStyle(color: Colors.white),
),
const Icon(
Icons.delete,
color: Colors.white,
),
],
),
),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) =>
_deleteScheduleFromList(_userSchedules[index]),
child: GestureDetector(
onTap: () => Navigator.of(context).push(
new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new ScheduleDetailed(
schedule: _userSchedules[index],
callback: this.callback,
);
},
fullscreenDialog: true),
),
child: SimpleShadow(
color: Color(0xffc0c0c0),
opacity: 0.7,
sigma: 4,
child: Container(
height: 90,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.only(left: 20, top: 20, right: 7),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SimpleShadow(
color: Color(0xffc0c0c0),
opacity: 0.7,
sigma: 4,
child: Transform(
transform:
Matrix4.translationValues(-20.0, 0.0, 0.0),
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
gradient:
LinearGradient(colors: gradientColors),
borderRadius:
BorderRadius.all(Radius.circular(10))),
child: Image.asset(
'assets/to-do-list.png',
cacheWidth: 30,
cacheHeight: 30,
color: Colors.white,
),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 180,
child: Text(
_userSchedules[index].title,
textAlign: TextAlign.start,
style: TextStyle(
color: Colors.black87,
fontSize: 16,
fontWeight: FontWeight.w600,
fontFamily: 'Poppins'),
),
),
Padding(
padding: EdgeInsets.only(top: 6),
child: Text(
_userSchedules[index]
.deviceList
.length
.toString() +
' '
'devices',
style: TextStyle(
color: darkGreyColor,
fontSize: 14,
),
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 10),
child: IconButton(
alignment: Alignment.centerRight,
icon: Icon(
Icons.date_range,
color: _userSchedules[index].startTime.length >
0 &&
_userSchedules[index].endTime.length > 0
? darkGreyColor
: baseColor,
),
onPressed: () {
_userSchedules[index].startTime.length == 0 &&
_userSchedules[index].endTime.length ==
0
? _openPopup(_userSchedules[index])
: new Container();
},
),
)
],
),
),
),
),
);
},
);
} else if (snapshot.hasError) {
const String message = 'Error;Failed to get schedule data!';
print('Error failed to get schedule list with scheduleFuture');
return _buildErrorWindow(height, message);
} else {
print('Resolving schedule future,loading indicator is displaying');
return _buildSpinner(height);
}
},
);
}
Widget _buildEmptyWidget(String message) {
...
}

Widget _buildSpinner(double height) {
...
}
Widget _buildErrorWindow(double height, String message) {
...
}

@override
void dispose() {
_startTimeController.dispose();
_endTimeController.dispose();
super.dispose();
}

}

你能试着移动吗if (this._currentIndex == 1) _scheduleFeature = _getSchedules();处于使用状态。

我还建议将两者作为单独的小部件,而不是作为呈现它们的函数。以便您可以使用initStatedidDependencyChange覆盖。

相关内容

最新更新