Reputation: 139
I have a page with a FutureBuilder and a custom widget with multiple FutureBuilders. My goal is to get Future after opening this page, but my FutureBuilders keep calling the Future twice. This is my page:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
LoggedUser loggedUser = Cache.getLoggedUser();
//zobrazení groupchatů
static Widget showGroupchats(List<Groupchat> list) {
List<Widget> children = [];
for (int i = 0; i < list.length; i++) {
children.add(GroupchatWidget(list[i]));
}
return Column(
children: children,
);
}
//widget
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: SingleChildScrollView(
child: SafeArea(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 15, left: 15),
child: FutureBuilder<ImageProvider>(
future: Buttons.getUserImage(loggedUser.Id, context),
builder: (BuildContext context,
AsyncSnapshot<ImageProvider> snapshot) {
return CircleAvatar(
radius: 20,
foregroundImage: snapshot.data,
backgroundImage: Settings.DefaultUserImage,
);
},
),
),
Padding(
padding: const EdgeInsets.only(left: 5, top: 10),
child: Text(
loggedUser.Username,
style: const TextStyle(fontSize: 20),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(top: 15, right: 15),
child: IconButton(
icon: SvgPicture.asset(
'assets/icons/settings.svg',
width: 25,
height: 25,
color: Theme.of(context).textTheme.bodyText1?.color,
),
onPressed: null //TODO editace profilu
),
),
],
),
Row(
children: <Widget>[
Flexible(
flex: 1,
child: Padding(
padding:
const EdgeInsets.only(left: 15, right: 15, top: 15),
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
hintText: 'groupchatSearch'.tr(),
prefixIcon: Container(
width: 5,
height: 5,
padding: const EdgeInsets.all(10),
child: SvgPicture.asset('assets/icons/search.svg',
color: Theme.of(context)
.textTheme
.bodyText1
?.color),
),
),
),
),
),
],
),
Padding(
padding: const EdgeInsets.only(left: 15, right: 15, top: 5),
child: FutureBuilder<List<Groupchat>>(
future: Buttons.getGroupchatList(context),
builder: (BuildContext context,
AsyncSnapshot<List<Groupchat>> snapshot) {
if (snapshot.hasData == false) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Padding(
padding: EdgeInsets.only(top: 15),
child: CircularProgressIndicator(),
),
],
);
} else {
return showGroupchats(snapshot.data!);
}
},
),
),
],
),
),
),
);
}
}
And custom widget for dispalying chat:
class GroupchatWidget extends StatefulWidget {
Groupchat groupchat;
@override
State<GroupchatWidget> createState() => _GroupchatWidgetState();
GroupchatWidget(this.groupchat, {Key? key}) : super(key: key);
}
class _GroupchatWidgetState extends State<GroupchatWidget> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 5, bottom: 5),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).focusColor,
borderRadius: BorderRadius.circular(15)),
child: ListTile(
leading: FutureBuilder<ImageProvider>(
future: Buttons.getGroupchatImage(widget.groupchat.Id, context),
builder:
(BuildContext context, AsyncSnapshot<ImageProvider> snapshot) {
return CircleAvatar(
radius: 25,
foregroundImage: snapshot.data,
backgroundImage: Settings.DefaultGroupchatImage,
);
},
),
title: Text(
widget.groupchat.Name,
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
subtitle: FutureBuilder<void>(
future:
Buttons.getNewGroupchatMessages(widget.groupchat.Id, context),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
return Text(
Cache.getLastMessage(widget.groupchat.Id).Text,
style: const TextStyle(fontSize: 15),
overflow: TextOverflow.ellipsis,
);
},
),
),
),
);
}
}
How do I prevent calling Future twice? I tried this but it doesnt work for me.
Upvotes: 0
Views: 715
Reputation: 1417
Try this
...
late Future<ImageProvider> imageProviderFuture;
@override
void initState() {
imageProviderFuture = Buttons.getGroupchatImage(widget.groupchat.Id, context),
super.initState();
}
...
//in your build
// future call imageProviderFuture
FutureBuilder<ImageProvider>(
future: imageProviderFuture,
)
Apply this to the rest of the places. P.S refer to thisLink
Upvotes: 1