Home > OS >  Flutter function running but UI not updating
Flutter function running but UI not updating

Time:01-29

I was trying to make a web app to visualise algorithm in flutter, I came across a short youtube video ( https://www.youtube.com/watch?v=IMK4yqlT24Q&t=672s) explaining it and I did a small test and it did work. Now when I want to build a complete web app it doesnt work. The way it is supposed to work is the list gets updated every cycle of loop while sorting and it gets printed. I tried using both Stream BUilder and set state for updating the UI but what happens is, A few bars moves for a second and then it stops

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  List<int> numbers = [];
  int sample = 500;

  @override
  void initState() {

    super.initState();
    random();
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    int counter = 0;
    return SafeArea(
      child: Row(
        children: [
          Container(
            height: size.height,
            width: size.width * 0.2,
            color: Colors.purple.shade500,
            child: Column(
              children: [
                SizedBox(
                  height: 30,
                  width: double.infinity,
                  child: MaterialButton(
                    onPressed: random,
                    child: Text('Randomise'),
                  ),
                ),
                SizedBox(
                  height: 30,
                  width: double.infinity,
                  child: MaterialButton(
                    onPressed: sort,
                    child: Text('Sort'),
                  ),
                ),
              ],
            ),
          ),
          Container(
            width: size.width * 0.8,
            height: size.height,
            color: Colors.white38,
            child: Align(
              alignment: Alignment.center,
              child: SizedBox(
                height: 600,
                width: 1000,
                child: Container(
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: numbers.map((int number){
                      counter  ;
                      return CustomPaint(   <-----Painting every bar of array
                        painter: BarPainter(number: number, index: counter, width: 2.0),
                      );
                    }).toList(),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  random() {
    numbers = [];
    for (var i = 0; i < sample; i  ) {
      numbers.add(Random().nextInt(sample));
    }
    setState(() {});
  }

  sort() async{
    for (var i = 0; i < numbers.length - 1; i  ) {
      for (var k = 0; k < numbers.length - 1 - i; k  ) {
        if (numbers[k] > numbers[k   1]) {
          var temp = numbers[k];
          numbers[k] = numbers[k   1];
          numbers[k   1] = temp;
        }
        await Future.delayed(Duration(microseconds: 50));
        setState(() {    <----updating build every loop

        });
      }
    }

  }
}

I know calling setState everytime is not good, but I did it just for testing, I usually put the row inside a Stream builder and keep adding the number list as a stream, which used to work fine. If I print a dummy counter inside the nested for of sort function, I can see that the loop is running, but for sume reason the Custom Paint doest seem to be updating the UI even if the delay time for the loop is increased.

class BarPainter extends CustomPainter {
  final double width;
  final int index;
  final int number;

  BarPainter({required this.number, required this.index, required this.width});

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint();
    paint.strokeWidth = width;
    paint.strokeCap = StrokeCap.square;
    paint.color = Colors.black;
    canvas.clipRect(Rect.fromLTRB(0, 0, 1000, 600));
    canvas.drawLine(Offset(index * width, 0),
        Offset(index * width, number.ceilToDouble()), paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return false;
  }
}

CodePudding user response:

You can return true from shouldRepaint. I do shortcut like oldDelegate != this;.

Check this question When is shouldRepaint method from custom painter class in flutter called?

  @override
  bool shouldRepaint(covariant BarPainter oldDelegate) {
    return oldDelegate != this;
  }
  •  Tags:  
  • Related