-1

Hi I am new to flutter and experimenting with statefull widget. I am trying to build a timer and want to show it in a Text.

This is my widget class.

class MobileVerification extends StatefulWidget {
  static const String MOBILE = 'mobile';
  final Map<String, dynamic> args;

  MobileVerification(this.args);

  @override
  State<StatefulWidget> createState() {
    return MobileVerificationState(args);
  }
}

This is my State class

class MobileVerificationState extends State<MobileVerification> {
  int remainingTime = 30;
  Timer timer;
  bool isResendBtnEnabled = false;

  MobileVerificationState(this.args);

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

  startResendTimer() {
    timer = new Timer.periodic(new Duration(seconds: 1), (time) {
      setState(() {
        remainingTime -= 1;
      });
      if (remainingTime == 0) {
           time.cancel();
           setState(() {
           isResendBtnEnabled = true;
        });
      }
    });
  }

  @override
  void dispose() {
    timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomScreenBg(
        body: _getOtpVerificationPage());
  }

  _getOtpVerificationPage() {
    return Container(
      margin: EdgeInsets.only(top: 24, bottom: 24, left: 12, right: 12),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          getResendWidget(),
          CustomButton(
            AppString.verify,
            isValidateBtnEnabled ? _onValidate : null,
            textColor: AppColor.WHITE.color,
            bgColor: AppColor.PRIMARY.color,
          ),
        ],
      ),
    );
  }

  Widget getResendWidget() {
    Logger.d(remainingTime.toString()); // Here I am getting changed value.
    if (isResendBtnEnabled) {
      return CustomButton(
        AppString.resend,
        _onResend,
        textColor: AppColor.WHITE.color,
        bgColor: AppColor.PRIMARY.color,
      );
    }
    return RichText(
      text: TextSpan(
        text: 'Resend in ${remainingTime}s',  <== But here value is not getting reflected. It stays same as 30
        style: TextStyle(color: AppColor.GRAY.color, fontSize: 18),
      ),
    );
  }
}

Timer is working perfectly fine, and I am getting updated value as well. But the updated value is not getting reflected inside RichText. Can someone point me out, where i am making the mistake? Thanks!!

Purushotam Kumar
  • 1,002
  • 2
  • 13
  • 23
  • 1
    It's hard to correct because we can't really see how you change the value. My first guess would be that you forgot to put SetState() around the place where you change the value but I can't be sure. – Lulupointu Jun 23 '20 at 13:43
  • If you can see the code, startResendTimer() is the method where i am updating the value with setState() method. getResendWidget() is the method where i am using it. Inside getResendWidget() i am getting the updated value, and i am setting that updated value inside a RichText(), but it is not getting reflected on screen. – Purushotam Kumar Jun 23 '20 at 13:48
  • What is CustomScreenBg ? I ran your example without it and it works fine so there must be the issue – Lulupointu Jun 23 '20 at 14:14
  • Tbh I don't understand how the double return in you build can work, for me it won't even compile and I've never seen such a thing before. – Lulupointu Jun 23 '20 at 14:21
  • Thanks for your comment, your comment made me understand the problem. This CustomScreenBg is another Stateful Widget. So, my mistake was, I was using one stateful widget inside another stateful widget. This was leading the problem. I converted nested one into stateless widget and it is working fine now. Sorry, I could not explain it in better terms. – Purushotam Kumar Jun 24 '20 at 10:56
  • No problem, happy for you that it worked ! – Lulupointu Jun 24 '20 at 11:54

1 Answers1

0

I was making a mistake. I was using StatefulWidget instead of statelessWidget for inheritance. Hope it can help someone. I have created my own custom widget to use. Structure of my widget is follows:

class CustomScreenBg extends StatefulWidget {
  final String title;
  final Widget body;

  CustomScreenBg(this.title, this.body);

  @override
  State<StatefulWidget> createState() {
   return _CustomScreenBgState(title, body);
  }
}

class _CustomScreenBgState extends State<CustomScreenBg> {
  final String title;
  final Widget body;

  _CustomScreenBgState(this.title, this.body);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      backgroundColor: AppColor.SNOW_WHITE.color,
      body: SingleChildScrollView(child: body),
      resizeToAvoidBottomInset: true,
    );
  }

}


I changed it to following and it is working fine.

class CustomScreenBg extends StatelessWidget {
  final String title;
  final Widget body;

  CustomScreenBg(this.title, this.body);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      backgroundColor: AppColor.SNOW_WHITE.color,
      body: SingleChildScrollView(child: body),
      resizeToAvoidBottomInset: true,
    );
  }
}

Purushotam Kumar
  • 1,002
  • 2
  • 13
  • 23