skip to Main Content

Note that this is for ListView.builder items, not general stateless vs stateful widget discussion.

Stateless listview builder item:

  • Pros
    • I assume each item can be quickly reused on a large list as they don’t contain any state
  • Cons
    • Any changes to any item would require to call setState on list view

Stateful listview builder item:

  • Pros
    • As recommended in Performance best practices, we can update each item via setState calls within the item widget, this has much less performance impact than calling setState on the whole list view widget.
  • Cons
    • As each row now has its own state, I guess they cannot be reused?

So which one would you recommend?

2

Answers


    • Stateless ListView builder items are efficient as they can be quickly
      reused on a large list, but any changes to any item require calling
      setState on the whole ListView widget.

    • Stateful ListView builder items allow updating each item via setState
      calls within the item widget, which has less performance impact than
      calling setState on the whole ListView widget, but each row has its
      own state and cannot be reused.

    Recommendation:

    Use the approach that best fits your specific use case and performance requirements. If you need to update individual items frequently and the ListView is large, consider using stateful items. If you have a smaller ListView and don’t need to update individual items frequently, stateless items may be sufficient.

    You can try giving a unique Key to each Stateful item in the ListView.builder to reuse them.

    Login or Signup to reply.
  1. if your ListView items are simple and don’t have any internal state or interactivity, using Stateless widgets would be more performant and easier to manage. If the items have internal state, interactivity, or more complex behavior, using Stateful widgets would be a better choice.

    Keep in mind that Flutter is optimized for fast UI updates, so the performance impact of Stateful vs Stateless ListView.builder items is not significant, especially for a small to medium-sized list of items. It is always recommended to profile your application and check performance metrics.

    Also do not forget about inherited widgets

    Inherited widgets provide a way to pass data down the widget tree without needing to manually pass it through every level. Inherited widgets can be useful when you want to share a common piece of information or state across multiple widgets without having to rebuild the entire widget tree when that information changes.

    Here is an example

    
    class CounterProvider extends InheritedWidget {
      final int counter;
      final VoidCallback increment;
    
      const CounterProvider({
        Key? key,
        required this.counter,
        required this.increment,
        required Widget child,
      }) : super(key: key, child: child);
    
      static CounterProvider of(BuildContext context) {
        return context.dependOnInheritedWidgetOfExactType<CounterProvider>()!;
      }
    
      @override
      bool updateShouldNotify(CounterProvider old) => counter != old.counter;
    }
    

    Wrap your ListView.builder with your custom InheritedWidget, passing the necessary data and methods:

    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('InheritedWidget Example')),
          body: CounterProvider(
            counter: _counter,
            increment: _incrementCounter,
            child: ListView.builder(
              itemCount: 10,
              itemBuilder: (context, index) => MyListItem(index),
            ),
          ),
        );
      }
    }
    

    Access the data from the InheritedWidget in your ListView.builder’s item:

    
    class MyListItem extends StatelessWidget {
      final int index;
    
      MyListItem(this.index);
    
      @override
      Widget build(BuildContext context) {
        final counterProvider = CounterProvider.of(context);
    
        return ListTile(
          title: Text('Item $index'),
          subtitle: Text('Counter: ${counterProvider.counter}'),
          onTap: () {
            counterProvider.increment();
          },
        );
      }
    }
    

    In this example, we’re using an InheritedWidget to manage and share a counter value across all ListView.builder items. Each item can access the counter and the increment method without having to pass them explicitly through constructors.

    Inherited widgets work well with both Stateless and Stateful ListView.builder items, depending on your specific use case. They can help you manage shared state across multiple widgets without needing to rebuild the entire tree when the data changes.

    There really is no correct answer to this. You pretty much have to do what is best for your usecase.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search