I have a complex UI , am displaying a listViewbuilder composed of many expansion tiles. At first , I retrieve the list of data show it , then I call on another function to which I give the id of my object to display details when I click on the expansion tile . The only problem here , is that the code complexity is too high , say we have 20 items in the list every time I call the function that returns the details of my item using futurebuilder or provider it will call the function 20 times even though I didn't click on the expansion tile to view the details. I want to be able to call my future function only when I click on the expansion tile. this is my view : enter image description here
and this is my code using provider and future builder
child: FutureBuilder(
future: futureQrqc,
builder: (BuildContext context,
AsyncSnapshot<QrqcDetails?> snapshot) {
if (snapshot.hasData) {
String? backgroundImage;
String? _setImage() {
String _mTitle = "${snapshot.data!.type}";
if(_mTitle == "Delivery") {
backgroundImage = "assets/icons/delivery.png";
} else if(_mTitle == "Security") {
backgroundImage = "assets/icons/security.png";
}
else if(_mTitle == "Quality") {
backgroundImage = "assets/icons/quality.png";
}
else if(_mTitle == "Cost") {
backgroundImage = "assets/icons/Cost.png";
}
else if(_mTitle == "People") {
backgroundImage = "assets/icons/people.png";
}
print("_mTitle: $_mTitle");
print("_mTitle: $backgroundImage");
return backgroundImage; // here it returns your _backgroundImage value
}
return Column(
children: [
ConditionalBuilder(
condition: myQrqcListViewModel
.articlesList[index].status ==
'INIT',
builder: (context) => Container(
// ignore: prefer_const_constructors
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20)),
),
foregroundDecoration:
const RotatedCornerDecoration(
color: Colors.orange,
geometry: BadgeGeometry(
width: 40,
height: 40,
cornerRadius: 16),
textSpan: TextSpan(
text: 'INIT',
style: TextStyle(
fontSize: 10,
letterSpacing: 1,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
child: ExpansionTile(
title: Text(
myQrqcListViewModel
.articlesList[index].id
.toString(),
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
leading: QrqcCardLeaing(
imgPath: _setImage(),
),
subtitle: Text(myQrqcListViewModel
.articlesList[index].title),
trailing: QrqcCardtrailing(percent: myQrqcListViewModel
.articlesList[index]
.progress
.toString(),text: myQrqcListViewModel
.articlesList[index]
.progress
.toString(),),
children: [
QrqcDetailsCardFirstRow(product: snapshot.data?.product?? "No product" ,role: myQrqcListViewModel
.articlesList[index].role, ),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: Image.asset(
"assets/icons/location.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data!.perimeter,
style: TextStyle(fontSize: 10),
)),
const SizedBox(width: 50),
Expanded(
child: Image.asset(
"assets/icons/calendar.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
convertDateTimeDisplay(snapshot.data!.creation_date),
style: TextStyle(fontSize: 10),
)),
],
),
const SizedBox(height: 10),
],
),
),
fallback: null,
),
ConditionalBuilder(
condition: myQrqcListViewModel
.articlesList[index].status ==
'SUBMITTED',
builder: (context) => Container(
// ignore: prefer_const_constructors
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20)),
),
foregroundDecoration:
const RotatedCornerDecoration(
color: Colors.blueAccent,
geometry: BadgeGeometry(
width: 40,
height: 40,
cornerRadius: 16),
textSpan: TextSpan(
text: 'SUB',
style: TextStyle(
fontSize: 10,
letterSpacing: 1,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
child: ExpansionTile(
leading: QrqcCardLeaing(
imgPath: _setImage(),
),
title: Text(
myQrqcListViewModel
.articlesList[index].id
.toString(),
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
subtitle: Text(myQrqcListViewModel
.articlesList[index].title),
trailing: Column(
children: [
Expanded(
child: CircularPercentIndicator(
radius: 20.0,
lineWidth: 2.0,
percent: double.parse(
myQrqcListViewModel
.articlesList[index]
.progress
.toString()) /
100,
center: Text(
myQrqcListViewModel
.articlesList[index]
.progress
.toString(),
style: const TextStyle(
fontSize: 10),
),
progressColor: kPrimaryColor,
)),
],
),
children: [
Row(
children: [
Expanded(
child: Image.asset(
"assets/icons/user.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
myQrqcListViewModel
.articlesList[index].role,
style: const TextStyle(
fontSize: 10),
)),
const SizedBox(width: 50),
Expanded(
child: Image.asset(
"assets/icons/product.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data?.product?? "No product" ,
style: TextStyle(fontSize: 10),
)),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: Image.asset(
"assets/icons/location.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data!.perimeter,
style: TextStyle(fontSize: 10),
)),
const SizedBox(width: 50),
Expanded(
child: Image.asset(
"assets/icons/calendar.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data!.creation_date,
style: TextStyle(fontSize: 10),
)),
],
),
const SizedBox(height: 10),
],
),
),
fallback: null,
),
ConditionalBuilder(
condition: myQrqcListViewModel
.articlesList[index].status ==
'VALIDATED',
builder: (context) => Container(
// ignore: prefer_const_constructors
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20)),
),
foregroundDecoration:
const RotatedCornerDecoration(
color: Colors.green,
geometry: BadgeGeometry(
width: 40,
height: 40,
cornerRadius: 16),
textSpan: TextSpan(
text: 'VALID',
style: TextStyle(
fontSize: 10,
letterSpacing: 1,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
child: ExpansionTile(
leading: QrqcCardLeaing(
imgPath: _setImage(),
),
title: Text(
myQrqcListViewModel
.articlesList[index].id
.toString(),
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
subtitle: Text(myQrqcListViewModel
.articlesList[index].title),
trailing: Column(
children: [
Expanded(
child: CircularPercentIndicator(
radius: 20.0,
lineWidth: 2.0,
percent: double.parse(
myQrqcListViewModel
.articlesList[index]
.progress
.toString()) /
100,
center: Text(
myQrqcListViewModel
.articlesList[index]
.progress
.toString(),
style: const TextStyle(
fontSize: 10),
),
progressColor: kPrimaryColor,
)),
],
),
children: [
Row(
children: [
Expanded(
child: Image.asset(
"assets/icons/user.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
myQrqcListViewModel
.articlesList[index].role,
style: const TextStyle(
fontSize: 10),
)),
const SizedBox(width: 50),
Expanded(
child: Image.asset(
"assets/icons/product.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data?.product?? "No product" ,
style: TextStyle(fontSize: 10),
)),
],
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: Image.asset(
"assets/icons/location.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data!.perimeter,
style: TextStyle(fontSize: 10),
)),
const SizedBox(width: 50),
Expanded(
child: Image.asset(
"assets/icons/calendar.png",
width: 20,
height: 20,
),
),
Expanded(
child: Text(
snapshot.data!.creation_date,
style: TextStyle(fontSize: 10),
)),
],
),
const SizedBox(height: 10),
],
),
),
fallback: null,
),
);
} else if (snapshot.hasError) {
return NoDataUI();
}
print(snapshot.error.toString());
return const Center(
child: CircularProgressIndicator());
})
If anyone can help please don't hesitate , this is an important issue to optimise my code before launching my app for users on stores . Thank you so much and happy coding :)
CodePudding user response:
You can wrap your ExpansionTile
with GestureDetector
or InkWell
and call the function in onTap
method.