0

I'm unsure of how to implement a FutureBuilder element alongside other non-asynchronous elements in my build tree. The fact that I'm using a Consumer which listens for changes within a ChangeNotifierprovider complicates things somewhat. Can I use both the provider and the FutureBuilder? In the following code, the relevant future I need to access is the socialProvider.currentavatar and socialProvider.currentname within the bottom navigation bar.

Widget build(BuildContext context) {
    var socialProvider = Provider.of<SocialProvider>(context);
    return new MaterialApp(
      home: new Scaffold(
        body: _myPages[_selectedIndex],
        
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: <BottomNavigationBarItem>[
          
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              title: Text('Home'),
            ),
            
            BottomNavigationBarItem(
                  icon: Consumer<SocialProvider>(
                  builder: (context, socialProvider, child) {
                return Image.network(socialProvider.currentavatar);
              }),
              title: Consumer<SocialProvider>(
                  builder: (context, socialProvider, child) {
                return Text(socialProvider.currentname);
              }),
            ),
           ],
          currentIndex: _selectedIndex,
          onTap: _onItemTapped,
       
        ),
      ),
    );
  }

And here's the code within my SocialProvider with ChangeNotifier class.

 class SocialProvider with ChangeNotifier {

  String currentname = loadCurrentName();
  String currentavatar = loadCurrentAvatar();

    loadCurrentName() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String currentname = await prefs.getString('currentname') ?? 'Anonymous';
    return currentname;
}
    loadCurrentAvatar() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String currentavatar = await prefs.getString('currentavatar') ?? "https://example.com/default.png";
    return currentavatar;
}
}

How can I implement the FutureBuilder so that I can grab the socialProvider.currentname and socialProvider.currentavatar?

Meggy
  • 1,491
  • 3
  • 28
  • 63

1 Answers1

1

Wrap your scaffold in FutureBuilder. You can use Future.wait to run 2 futures in FutureBuilder. Since you are not getting the data from Snapshot, you can get rid of those consumers unless you are planning to update those fields.

Widget build(BuildContext context) {
  var socialProvider = Provider.of<SocialProvider>(context);
  return new MaterialApp(
    home: FutureBuilder(
      future: Future.wait([socialProvider.loadCurrentName(), socialProvider.loadCurrentAvatar()]),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Scaffold(
            body: _myPages[_selectedIndex],

            bottomNavigationBar: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              items: <BottomNavigationBarItem>[

                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  title: Text('Home'),
                ),

                BottomNavigationBarItem(
                  icon: Consumer<SocialProvider>(
                  builder: (context, socialProvider, child) {
                    return Image.network(snapshot.data[1]);
                  }),
                  title: Consumer<SocialProvider>(
                    builder: (context, socialProvider, child) {
                      return Text(snapshot.data[0]);
                    }),
                ),
              ],
              currentIndex: _selectedIndex,
              onTap: _onItemTapped,

            ),
          );
        } else if(snapshot.hasError) {
          // handle error.
        } else{
          // handle loading.

        }
      }
    ),
  );
}
 class SocialProvider with ChangeNotifier {

  String currentname = loadCurrentName();
  String currentavatar = loadCurrentAvatar();

    Future<String> loadCurrentName() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String currentname = await prefs.getString('currentname') ?? 'Anonymous';
    return currentname;
}
    Future<String> loadCurrentAvatar() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String currentavatar = await prefs.getString('currentavatar') ?? "https://example.com/default.png";
    return currentavatar;
}
}
Zeeshan Hussain
  • 802
  • 6
  • 9
  • I got an error from Android Studio on this line "future: Future.wait([socialProvider.loadCurrentName(), socialProvider.loadCurrentAvatar()])," Here's the error : Couldn't infer type parameter 'E'. Tried to infer 'String' for 'E' which doesn't work: Return type declared as 'List' used where 'List>' is required. The type 'String' was inferred from: Parameter 'element' declared as 'E' but argument is 'String'. Consider passing explicit type argument(s) to the generic. The argument type 'List' can't be assigned to the parameter type 'Iterable>'. – Meggy Jul 29 '20 at 17:42
  • @Meggy I have updated my code. You can try now, I just made those 2 functions call a future. – Zeeshan Hussain Jul 29 '20 at 17:44
  • Thanks Zeeshan. Unfortunately the whole scaffold is now throwing this error; This function has a return type of 'Scaffold', but doesn't end with a return statement. Try adding a return statement, or changing the return type to 'void'. – Meggy Jul 29 '20 at 18:15
  • @Meggy I'm not sure where it's happening but it could be because you are not returning anything in the error handle case and loading case. if you don't want to handle them separately then just do return Container();. Let me know if this does not work, then I will update my answer again. – Zeeshan Hussain Jul 29 '20 at 18:21
  • That's great Zeeshan. Thanks very much for your help! I just added return Center(child: Text('Data unavailable')); for now. BTW you might want to edit return Image.network(snapshot.data[0]); to be return Image.network(snapshot.data[1]); – Meggy Jul 29 '20 at 18:38
  • @Meggy Thanks for the suggestion, I have edited my answer. – Zeeshan Hussain Jul 29 '20 at 18:41