skip to Main Content

I am the beginner of Flutter. Recently stuck in creating widget.

Here is my condition. I use SharedPreferences getting Boolean value at first then create widget. However, my widget always show in TRUE condition, even though the Boolean value is false. In my widget, there is a GestureDetector with onTap(). My widget will change to right status after I tap in it. But I wish it should be the right status while initial creation. Thus, I am really confused about that. I appreciate your help very much.

SharedPreferences For getting data.

  String id = "";
  Future _UIsetting() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    flip=prefs.getBool('flip')!;
    id=prefs.getString("ID").toString();
  }

Widget build

@override
Widget build(BuildContext context) {

 _UIsetting(); //getting data

 return Container(
    child:Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [

        **//something wrong here. Nothing show at first**
        Text("HI $id"),

        Container(
            color: sliver,
            child: GestureDetector(
                onTap: (){
                  setState(() {
                    _flipCheck();
                  });
                },
                child: AnimatedSwitcher(
                  duration: Duration(seconds: 1),
                  transitionBuilder: (Widget widget, Animation<double> animation){
                    final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation);
                    return AnimatedBuilder(
                      animation: rotateAnim,
                      child: widget,
                      builder: (context, widget) {
                        final isUnder = (ValueKey(flip) != widget);
                        final value = isUnder ? min(rotateAnim.value, pi / 2) : rotateAnim.value;
                        return Transform(
                          transform: Matrix4.rotationY(value),
                          child: widget,
                          alignment: Alignment.center,
                        );
                      },
                    );
                  },

                  **//something wrong here. Showing TRUE condition at first(Not the right status).**
                  child: flip?
                  SizedBox(
                    key: ValueKey(0),
                    width: MediaQuery.of(context).size.width,
                    height: 250,
                    child: Image.asset('assets/work1.png'),
                  ):
                  SizedBox(
                    key: ValueKey(1),
                    width: MediaQuery.of(context).size.width,
                    height: 250,
                    child: Image.asset('assets/work2.png'),
                  ),
                )
            )
        ),

        **//something wrong here. Showing TRUE condition at first(Not the right status).**
        flip?Text("TRUE Condition"):Text("FALSE Condition"),
      ],
    )
);}

_flipCheck() checking flip picture or not

Future _flipCheck() async{

  SharedPreferences prefs = await SharedPreferences.getInstance();
  previous=prefs.getInt('previous_timestamp')!;
  flip=prefs.getBool('flip')!;
  int now=DateTime.now().millisecondsSinceEpoch;

  if((now-previous)~/3600000>=8){
    //update time
    prefs.setInt('previous_timestamp', now) ;
    flip=true;
    prefs.setBool('flip', true);
  }else{
    flip=false;
    prefs.setBool('flip', false);
  }

}

All code is in class myAPPState extends State<myAPP>{}

2

Answers


  1. It seems like you’re facing an issue where the initial state of flip is not reflected in your widget. This could be due to the asynchronous nature of SharedPreferences.getInstance().

    One approach to handle this is to use a FutureBuilder to wait for the result of SharedPreferences.getInstance() before building the widget tree. Here’s how you can modify your code:

    class myAPPState extends State<myAPP> {
      late String id;
      late bool flip;
    
      Future<void> _UIsetting() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        setState(() {
          flip = prefs.getBool('flip')!;
          id = prefs.getString("ID").toString();
        });
      }
    
      @override
      void initState() {
        super.initState();
        _UIsetting(); // Call _UIsetting in initState
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: _UIsetting(), // Use FutureBuilder to wait for _UIsetting to complete
          builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return Container(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text("HI $id"),
                    Container(
                      color: sliver,
                      child: GestureDetector(
                        onTap: () {
                          setState(() {
                            _flipCheck();
                          });
                        },
                        child: AnimatedSwitcher(
                          // ... Rest of your code ...
                        ),
                      ),
                    ),
                    flip ? Text("TRUE Condition") : Text("FALSE Condition"),
                  ],
                ),
              );
            } else {
              return CircularProgressIndicator(); // Show a loading indicator while waiting for SharedPreferences
            }
          },
        );
      }
    
      // ... Rest of your code ...
    }
    

    This modification ensures that _UIsetting() is called before the widget tree is built, which should resolve the issue with the initial state of flip.

    Login or Signup to reply.
  2. Another option would be to use run method after screen construction has finished.
    https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html

    @override
    void initState() {
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        await _flipCheck();
        setState(() {});
      });
    }
    

    But @Hasib Akon answer with FutureBuilder is better if it applies to you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search