jsfrz
jsfrz

Reputation: 139

Flutter FutureBuilder called twice

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,
              );
            },
          ),
        ),
      ),
    );
  }
}

This is the output: enter image description here

How do I prevent calling Future twice? I tried this but it doesnt work for me.

Upvotes: 0

Views: 715

Answers (1)

Davis
Davis

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

Related Questions