0

I'm trying to include FutureBuilder but it goes into the CircularProgressIndicator() and doesn't load the actual screen code after the value of 'time' is populated by calling from SharedPreferences and the ConnectionState is done. It just gets stuck in the CircularProgressIndicator().

What am I missing here?

Future<int> getTime() async {
  await MySharedPreferences.instance.getIntValue("time_key").then((value) =>
    setState(() {
     time= value;
}));
     return time;
        

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

MySharedPreferences.instance
    .getStringValue("title_key")
    .then((value) => setState(() {
  title = value;
}));



controller =
    AnimationController(vsync: this,
        duration: Duration(
            seconds: time));
controller2 =
    AnimationController(vsync: this,
        duration: Duration(
            seconds: time));
controller3 =
    AnimationController(vsync: this,
        duration: Duration(
            seconds: 1));
    ....}
      
@override
Widget build(BuildContext context){

            return WillPopScope(

              onWillPop: () async => false,
              child: Scaffold(

                backgroundColor: Colors.black,
                body: FutureBuilder<int>
                  (
                  future: getTime(),
                builder: ( BuildContext context, AsyncSnapshot<int> snapshot) {
                  print(snapshot);
                  print(time);
                  if (snapshot.connectionState == ConnectionState.done) {
                    print(time);
                    return SafeArea(

                      minimum: const EdgeInsets.all(20.0),
                      child: Stack(
                        children: <Widget>[
                          Container(
                            child:
                            Align(
                              alignment: FractionalOffset.topCenter,
                              child: AspectRatio(
                                aspectRatio: 1.0,
                                child: Container(
                                  height: MediaQuery
                                      .of(context)
                                      .size
                                      .height / 2,
                                  width: MediaQuery
                                      .of(context)
                                      .size
                                      .height / 2,
                                  decoration: BoxDecoration(
                                    //shape: BoxShape.rectangle,
                                      color: Colors.black,
                                      image: DecorationImage(

                                        image: AssetImage(
                                            "assets/images/moon.png"),
                                        fit: BoxFit.fill,
                                      )
                                  ),
                                ),
                              ),
                            ),
                          ),
                          build_animation(),
                          

                        ],
                      ),
                    );
                  }


                  else {
                    return CircularProgressIndicator();
                  }
                }


                  ),
  ),
            );
        }


build_animation() {
  return AnimatedBuilder(
      animation: controller,
      builder: (context, child) {
        return Stack(
          children: <Widget>[
            Padding(
              padding: EdgeInsets.all(0.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Expanded(
                    child: Align(
                      alignment: FractionalOffset.bottomCenter,
                      child: AspectRatio(
                        aspectRatio: 1.0,
                        child: Stack(
                          children: <Widget>[
                            Padding(
                              padding: EdgeInsets.only(top:MediaQuery.of(context).size.height / 6),
                              child: Column(
                                children: <Widget>[

                                  Text(
                                    title.toString(),
                                    style: TextStyle(
                                      fontSize: 20.0,
                                      color: Colors.black,fontWeight: FontWeight.bold,),
                                  ),
                                  new Container(
                                    child: new Center(
                                      child: new Countdown(
                                        animation: new StepTween(
                                          begin: time,
                                          end: 0,
                                        ).animate(controller),
         .....
nvoigt
  • 75,013
  • 26
  • 93
  • 142
int_string
  • 19
  • 3
  • as i see the code `FutureBuilder` builds and even multiple times, add `print(snapshot`) before `if (snapshot.connectionState == ConnectionState.done) {` - what do you see on the logs? – pskink Sep 17 '20 at 04:26
  • It's printing the following message continuously:flutter: AsyncSnapshot(ConnectionState.waiting, 17, null) . Why is it stuck in waiting state? Am I doing something wrong with: Future getTime() async { await MySharedPreferences.instance.getIntValue("time_key").then((value) => setState(() { time= value; })); return time; } I need the 'time' value (which is an int) from the shared preferences . This value is used for duration of the Animation controller in the Build. – int_string Sep 17 '20 at 05:18
  • `Future getTime() => MySharedPreferences.instance.getIntValue("time_key")` – pskink Sep 17 '20 at 05:23
  • Yes, that solves the ConnectionState.waiting issue, but it is not updating the time value to the value obtained from shared preference. Any ideas? – int_string Sep 17 '20 at 05:28
  • you are not using `time` variable in the future builder code you posted – pskink Sep 17 '20 at 05:36
  • I have updated the code to include the usage of 'time' variable. – int_string Sep 17 '20 at 05:45

1 Answers1

0

For starters, you do not need to setState for the result of the Future you use with a FutureBuilder. The whole point of the FutureBuilder class is to handle that for you. Also, it's best to not mix .then() and await until you have more experience. They work well together, but concentrate at one concept at a time while you are still learning.

This is your method after it's trimmed down (your choice if that's still worth a method, or if your want to put that code into iniState directly):

 Future<int> getTime() async {
    final value = await MySharedPreferences.instance.getIntValue("time_key");
    return value;
 }

You should not give that method to your FutureBuilder, otherwise you will start it anew every time build is called for any reason.

So you initState should look like this:

Future<int> futureIntFromPreferences;

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

  futureIntFromPreferences = getTime();
}

Then you can use that in your FutureBuilder:

body: FutureBuilder<int>(
        future: futureIntFromPreferences,
        builder: (BuildContext context, AsyncSnapshot<int> snapshot) {

For a detailed explanation, read What is a Future and how do I use it?

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • thanks...your explanation makes things easier to understand. However, I am still not able to update the value of the 'time' variable (for the animation controller.) Is it even allowed to update the controller duration value with a Future Builder? – int_string Sep 17 '20 at 06:23