Home > Mobile >  Flutter how to user setState()
Flutter how to user setState()

Time:06-17

One of my routes shows current data which is stored in firestore database. I am calling the function to retrieve the data from firestore in the initState methode. The page will show all the data which are retrieved from firestore. It works fine ie, when the user navigates to this page (quotesPage) it shows the data. But while navigating, for some fraction of seconds it shows error that the local variable which stores the retrieved data is null. It happens for only that fraction of seconds after which it receives the data and shows the data. So when the user navigates to that page, I want to show a progress indicator untill it receive the data. here is my code,

Map<String, dynamic> userInfo = {};

  Future<void> getQoutes() async {
    var data = await FirebaseFirestore.instance.collection('user').doc(auth.currentUser!.uid).get();
    setState(() {
      userInfo = data.data() as Map<String, dynamic>;
    });
  }

@override
  void initState() {
    getQoutes();
    super.initState();
  }


Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Some Quotes',
        ),
        backgroundColor: Colors.deepOrange,
      ),
      body: SingleChildScrollView(
        child: Container(
          height: MediaQuery.of(context).size.height,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Expanded(
                child: ListView.builder(
                  itemCount: 3,
                  scrollDirection: Axis.vertical,
                  itemBuilder: (context, index) {
                    return Card_fun(userInfo['quotes'][index]);
                  }
                )
              )
            ],
          ),
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await popUpForm();
        },
      ),
    );
 

I am calling the function getQuotes() from initState() which will store the data to Map variable userInfo. So how to show a progress indicator untill the variable 'userInfo' gets data ? Can anyone help ?


This is the updated code

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Some Quotes',
        ),
        backgroundColor: Colors.deepOrange,
      ),
      body: SingleChildScrollView(
        child: Container(
          height: MediaQuery.of(context).size.height,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              FutureBuilder<void>(
                future: getQoutes(),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  switch (snapshot.connectionState) {
                    case ConnectionState.done:
                      if(snapshot.hasError) {
                        return Text('Error : ${snapshot.error}');
                      }
                      return Expanded(
                        child: ListView.builder(
                        itemCount: 3,
                        scrollDirection: Axis.vertical,
                        itemBuilder: (context, index) {
                          return Card_fun(userInfo['quotes'][index]);
                        }
                        )
                      );
                    default:
                      return const CircularProgressIndicator();
                  }
                },
              )
            ],
          ),
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await popUpForm();
        },
      ),
    );

CodePudding user response:

You should try with Future builder or stream builder and here is the example with Future builder

FutureBuilder<String>(
    future: getQoutes(), // async work
    builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
       switch (snapshot.connectionState) {
         case ConnectionState.waiting: return CircularProgressIndicator();
         default:
           if (snapshot.hasError)
              return Text('Error: ${snapshot.error}');
           else
          return Expanded(
                child: ListView.builder(
                  itemCount: 3,
                  scrollDirection: Axis.vertical,
                  itemBuilder: (context, index) {
                    return Card_fun(userInfo['quotes'][index]);
                  }
                )
              );
        }
      },
    )

For more read this article

CodePudding user response:

another approach that might be worth looking at is using a addPostFrameCallback method called from your initState in which you can await the necessary condition and take appropriate action and trigger a setState.

  • Related