Widget rebuild provider flashing lag optimization

25 Views Asked by At

I have a music application, I want to display music notes each second with a svg file. I have a music keyboard provider that notifies every second, all listeners. Each time, it rebuilds the widget I think completely. I use a controller to load an svg file to render music notes on a music staff (bunch of music notes). The widget is lagging and there's a flash every second.

class StaffView extends StatelessWidget {
  late Future<String> _svgFuture;

  late String _currentSvg = "";

  @override
  Widget build(BuildContext context) {
    

    final ScaleProvider scaleProvider = context.watch<ScaleProvider>();
    Scale? myScale = scaleProvider.getScale();

    PianoKeysProvider pkp = context.watch<PianoKeysProvider>();
    int noteScalePosition = pkp.getIndexPosition();

    //Faire la validation
    if(_currentSvg == "")
    {
      _svgFuture = GenerateStaffSvg(myScale, noteScalePosition);
      pkp.RestartScale();
    }

How can I use the provider and watch for change every seconds and not rebuild the widget completely every time? Will it be useful to use a stafeful widget and use a setstate to rebuild just the svg?

The build :

return FutureBuilder<String>(
      future: _svgFuture,
      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else if (snapshot.hasError) {
          return Text('Error : ${snapshot.error}');
        } else {
          
          _currentSvg = snapshot.data!;
          return Expanded(
            child: Container(
              color: Colors.white,
              child: SingleChildScrollView(
                child: FittedBox(
                  fit: BoxFit.fill,
                    child: SvgPicture.string(
                      _currentSvg,
                      width: 500,
                      height: 500,
                    ),
                  ),
                ),
              ),
            );
        }
      },
    );

Where the widget is called :

child: Container(
          color:Colors.black,
          child: Column(
            children: [
              // First child, an empty space
              Conditional.single(
                context: context,
                conditionBuilder: (BuildContext context) => _heightRatio == 2,
                widgetBuilder: (BuildContext context) => Flexible(
                    flex: 3,
                    child: StaffView(
                  ), 
                  ),
                  fallbackBuilder: (BuildContext context) => Container(),
                ),
              
              // Second child, the piano keyboard
              Flexible(
                flex: 1,
                child: Consumer<PianoKeysProvider>(
                  builder: (context, pianoKeysProvider, child) {
                    return ListView.builder(
                  itemCount: 7,
                  scrollDirection: Axis.horizontal,
                  controller: ScrollController(initialScrollOffset: 1500.0),
                  itemBuilder: (BuildContext context, int index) {
                    final int i = index * 12;

Thank you so much

I tried using the snapshot data to avoid loading the svg image all the time, but I have the same problem.

0

There are 0 best solutions below