Search code examples
fluttersetstateprovider

Everytime provider updates setState() or markNeedsBuild() called during build


Evertime the setCountDown method is called i get an exception SetStateCalled during build ,,, please help! . I have to display this countdown in a previous screen too , Lets call it screen A and from A i pushReplaced and came to this Charging Screen which displays countdown and uses provider too . But everytime I update the provider value I get an error . It works fine in the debug mode but as soon as build a release it works weirdly . Please help!!!!

import 'dart:async';
import 'dart:developer';
import 'package:chargeapp_master/ChangeNotifiers/ChargeTimeNotifier.dart';
import 'package:chargeapp_master/Screens/main_map_screen.dart';
import 'package:chargeapp_master/Screens/navigation.dart';
import 'package:chargeapp_master/Screens/profile_screens/profile_screen.dart';
import 'package:chargeapp_master/Screens/wallet_screens/wallet_screen.dart';
import 'package:chargeapp_master/assistants/assistant_methods.dart';
import 'package:chargeapp_master/assistants/bluetooth_assistants.dart';
import 'package:chargeapp_master/widgets/bottbar.dart';

import 'package:circular_countdown_timer/circular_countdown_timer.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_fonts/google_fonts.dart';
import '../User Details.dart';
import '../main.dart';
import 'Charging_summary_screen.dart';
import 'package:provider/provider.dart';

class Charging_screen extends StatefulWidget {
  int duration;
  String amount;
  Charging_screen({Key? key, required this.duration, required this.amount})
      : super(key: key);

  @override
  _Charging_screenState createState() => _Charging_screenState();
}

class _Charging_screenState extends State<Charging_screen> with ChangeNotifier {
  double h(double height) {
    return MediaQuery.of(context).size.height * height;
  }

  double w(double width) {
    return MediaQuery.of(context).size.width * width;
  }

  void showNotification(String dat) {
    flutterLocalNotificationsPlugin.show(
        0,
        "Powerstrip",
        "Charging $dat",
        NotificationDetails(
            android: AndroidNotificationDetails(channel.id, channel.name,
                importance: Importance.high,
                color: Colors.blue,
                playSound: true,
                icon: '@mipmap/ic_launcher')));
  }

  CountDownController _controller = CountDownController();
  Timer? countdownTimer;
  Duration myDuration = Duration();

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

    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      Provider.of<ChargeTimeProvider>(context, listen: false)
          .setDuration(Duration(minutes: widget.duration));
      startTimer();
    });
  }

  void setCountDown() {
    final reduceSecondsBy = 1;

    var seconds = Provider.of<ChargeTimeProvider>(context, listen: false)
            .getDuration()
            .inSeconds -
        reduceSecondsBy;
    log("got seconds from provider " + seconds.toString());
    if (seconds < 0) {
      countdownTimer?.cancel();

      showNotification("Stopped");
      log("$charging");
    } else {
      Provider.of<ChargeTimeProvider>(context, listen: false)
          .setDuration(Duration(seconds: seconds));
      // myDuration = Duration(seconds: seconds);
    }

    // setState(() {
    //   final seconds = myDuration.inSeconds - reduceSecondsBy;
    // });
  }

  void startTimer() {
    showNotification("Started");
    context.read<ChargeTimeProvider>().setChargeStatus(true);
    countdownTimer =
        Timer.periodic(Duration(seconds: 1), (_) => setCountDown());
  }

  void stoptimer() {
    Provider.of<ChargeTimeProvider>(context, listen: false)
        .setChargeStatus(false);
    // context.read<ChargeTimeProvider>().setChargeStatus(false);
    log("$charging");
    countdownTimer?.cancel();
  }

  String mins = "";
  String sec = "";
  var minutesChargedfor;
  Future<bool> _onWillPop() async {
    return (await showDialog(
          barrierDismissible: true,
          context: context,
          builder: (context) => AlertDialog(
            backgroundColor: Colors.black,
            title: Text(
              'Are you sure?',
              style: GoogleFonts.sulphurPoint(color: Colors.white),
            ),
            content: Text(
              'Do you want to go to home screen',
              style: GoogleFonts.sulphurPoint(color: Colors.white),
            ),
            actions: <Widget>[
              TextButton(
                onPressed: () {
                  Navigator.pop(context);
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (BuildContext) => Navigation()));
                },
                child: const Text('Yes'),
              ),
            ],
          ),
        )) ??
        false;
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _onWillPop(),
      child: Scaffold(
        backgroundColor: Color(0xff1B1D20),
        body: Stack(
          children: [
            Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(height: 70),
                Center(
                  child: Container(
                    padding: EdgeInsets.all(12),
                    // margin: EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(7),
                    ),
                    child: Text(
                      "Congratulations, you've added Green miles🍀",
                      style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                          color: Colors.green.shade600),
                    ),
                  ),
                ),
                const SizedBox(
                  height: 20,
                ),
                Center(
                  child: Column(
                    children: [
                      Center(
                        child: CircularCountDownTimer(
                          duration: widget.duration * 60,
                          controller: _controller,
                          width: MediaQuery.of(context).size.width / 2,
                          height: MediaQuery.of(context).size.height / 2,
                          ringColor: Colors.grey[400]!,
                          ringGradient: const LinearGradient(
                              colors: [Colors.white10, Colors.white70]),
                          fillColor: Colors.blue,
                          fillGradient: LinearGradient(colors: [
                            Colors.blue.shade300,
                            Colors.blue.shade900
                          ]),
                          backgroundColor: Colors.grey[500],
                          backgroundGradient: LinearGradient(colors: [
                            Colors.grey.shade900,
                            Colors.grey.shade500
                          ]),
                          strokeWidth: 20.0,
                          strokeCap: StrokeCap.round,
                          textStyle: const TextStyle(
                              fontSize: 33.0,
                              color: Colors.white,
                              fontWeight: FontWeight.bold),
                          // textFormat: CountdownTextFormat.MM_SS,
                          isTimerTextShown: true,
                          isReverse: false,
                          onComplete: () async {
                            var secondsChargedfor = widget.duration * 60;

                            var res = AssistantMethods.stopCharging(
                                secondsChargedfor, "0");
                            if (res != "failure") {
                              await Ble.disconnectDevice(connectedDevice);

                              stoptimer();
                              Navigator.pushReplacement(
                                  context,
                                  MaterialPageRoute(
                                      builder: (context) => Charging_summary(
                                          amount: widget.amount,
                                          duration: widget.duration,
                                          mins: mins,
                                          sec: sec)));
                            } else {
                              Fluttertoast.showToast(msg: res);
                            }
                            Ble.disconnectDevice(connectedDevice);

                            Navigator.pushReplacement(
                                context,
                                MaterialPageRoute(
                                    builder: (_) => Charging_summary(
                                        amount: widget.amount,
                                        duration: widget.duration,
                                        mins: mins,
                                        sec: sec)));
                          },
                        ),
                      ),
                      //   SizedBox(height: 10,),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: const [
                          Icon(
                            Icons.flash_on,
                            size: 30,
                            color: Colors.blue,
                          ),
                          SizedBox(
                            width: 7,
                          ),
                          Text(
                            "Charging",
                            style: TextStyle(
                                fontSize: 16,
                                color: Colors.white,
                                fontWeight: FontWeight.w400),
                          )
                        ],
                      ),

                      BuildTime(),
                    ],
                  ),
                ),
                const SizedBox(
                  height: 40,
                ),
                Container(
                  decoration: const BoxDecoration(
                    borderRadius: BorderRadius.all(Radius.circular(10)),
                  ),
                  child: Container(
                    padding: EdgeInsets.all(15),
                    // height: 130,
                    // width:MediaQuery.of(context).size.width ,
                    decoration: const BoxDecoration(
                      color: Colors.black,
                      borderRadius: BorderRadius.only(
                          topRight: Radius.circular(10.0),
                          topLeft: Radius.circular(10.0)),
                    ),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Column(
                              mainAxisAlignment: MainAxisAlignment.start,
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Text(
                                  user_device_id.toString(),
                                  style: const TextStyle(
                                      fontSize: 14,
                                      color: Colors.white,
                                      fontWeight: FontWeight.w400),
                                ),
                              ],
                            ),
                            device_type == 0
                                ? Text(
                                    "₹${widget.amount}",
                                    style: const TextStyle(
                                        fontWeight: FontWeight.w500,
                                        fontSize: 18,
                                        color: Colors.white),
                                  )
                                : const Text(""),
                          ],
                        ),
                        const SizedBox(
                          height: 10,
                        ),
                        Row(
                          children: [
                            Expanded(
                              child: ElevatedButton(
                                style: ElevatedButton.styleFrom(
                                  shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(10),
                                  ),
                                  primary: Colors.red.shade900,
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 50, vertical: 15),
                                  // minimumSize: Size(50,20 ),
                                ),
                                child: const Text(
                                  "Stop",
                                  style: TextStyle(
                                      fontSize: 15, color: Colors.white),
                                ),
                                onPressed: () async {
                                  var secondsChargedfor = widget.duration * 60;
                                  secondsChargedfor = secondsChargedfor -
                                      (int.parse(mins) * 60 + int.parse(sec));
                                  log(secondsChargedfor.toString());
                                  var res = AssistantMethods.stopCharging(
                                      secondsChargedfor, "1");
                                  if (res != "failure") {
                                    await Ble.startStopTimer(services,
                                        0.toString()); // to stop the charging
                                    _controller.pause();
                                    await Ble.disconnectDevice(connectedDevice);

                                    stoptimer();
                                    Navigator.pushReplacement(
                                        context,
                                        MaterialPageRoute(
                                            builder: (context) =>
                                                Charging_summary(
                                                    amount: widget.amount,
                                                    duration: widget.duration,
                                                    mins: mins,
                                                    sec: sec)));
                                  } else {
                                    Fluttertoast.showToast(msg: res);
                                  }
                                },
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
        //bottomNavigationBar: bottbar(),
      ),
    );
  }

  Widget BuildTime() {
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final hours = twoDigits(
        context.read<ChargeTimeProvider>().getDuration().inHours.remainder(24));
    final minutes = twoDigits(context
        .read<ChargeTimeProvider>()
        .getDuration()
        .inMinutes
        .remainder(60));
    final seconds = twoDigits(context
        .read<ChargeTimeProvider>()
        .getDuration()
        .inSeconds
        .remainder(60));
    mins = minutes;
    sec = seconds;

    Provider.of<ChargeTimeProvider>(context, listen: true)
        .setTime("$hours:$minutes:$seconds");

    return Consumer<ChargeTimeProvider>(
        builder: (context, chargetimenotifier, child) => Text(
              "${chargetimenotifier.getTime()}  Time Remaining",
              style: TextStyle(fontSize: 14, color: Colors.white),
            ));
  }

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

Solution

  • Add Some Delay

      Future.delayed(const Duration(milliseconds: 500), () {
        
        // Here you can write your code
        
          setState(() {
            // Here you can write your code for open new view
          });
        
        });