How I can update a listview element without set state?

Viewed 205

I have a List view. Builder with an image. The image has an opacity depending on a provider element (provider element is true, the opacity is 1, if it false opacity is 0). Then I have another class, from that class I can update the provider of the list view image, however in order to change the effect of the change, I have to set state the list view widget.

Even if it is good and is working properly, I don't want to do that because when I set state the list view widget, the list view position restart and I need to scroll again at the element of the list view, I know that I can save the scroll position (with a controller) but because my list view is too large, it needs a lot of time to get at the position, so I don't like it.

Any idea ?

1 Answers

If you want to rebuild the UI without calling setState, you can use the help of ValueNotifier and the ValueListenableBuilder widget.

Here is a simplified counter app, if you take a look at the console, you'll see that print('build'); is only called initially running the build method and not called again when calling _increment():


import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: PageLoadApp()));
final counter = ValueNotifier<int>(0);

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

  @override
  State<PageLoadApp> createState() => _PageLoadAppState();
}

class _PageLoadAppState extends State<PageLoadApp> {
  void _increment() {
    counter.value++;
  }

  @override
  Widget build(BuildContext context) {
    print('build');
    return Scaffold(
        body: Scaffold(
            body: ValueListenableBuilder<int>(
                valueListenable: counter,
                builder: (context, value, _) {
                  return Center(
                    child: Text('$value', style: const TextStyle(fontSize: 30)),
                  );
                }),
            floatingActionButton: FloatingActionButton(
              onPressed: _increment,
              child: const Icon(Icons.add),
            )));
  }
}

Additionally, this widget can be a StatelessWidget.

Since you haven't provided a code example, you'll have to adapt this provided example for your case.


Here is a YouTube video by the Google team explaining ValueListenableBuilder

Related