Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update a single item in flutter list, as a best way

Tags:

flutter

dart

People also ask

How do you replace data in a list in flutter?

If you know the index of the element you want to replace, you don't need to remove existing element from the List. You can assign the new element by index.

How do you change the index of an item in a list in flutter?

You can use insert , but I solved by reversing the listView. @YeasinSheikh reversing the list only make it upside down.. I just want to push an item to index first and reduce others indexes by -1.


This is my way

foods[foods.indexWhere((element) => element.uid == food.uid)] = food;

some validation should be applied to avoid any null reference issues


You can do so by nesting a stream builder in each item builder. This works by using the initialData argument of the stream builder.

final Stream<Item> updateItemsSteram = ...;
final List<Item> initialList = [...];
ListView.builder(
  itemBuilder: (context, idx) {
            return StreamBuilder<Item>(
                initialData: initialList[idx],
                stream: updateItemsSteram.where((item) => item.id == initialList[idx].id),
                builder: (ctx, snapshot) => MyCustomWidget(snapshot.data)
             );
          }
)

Though, you may want to benchmark this and compare it to updating the whole list, because flutter reuses the elements in all cases and the streams might just bring more overhead.


I solved this problem with a statefull widget to represent a item in ListView. If you want manipulate just a item data, you do it by Item widget. If you add or remove a item on the tail of list, the list will be not rerendered.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
import 'package:random_color/random_color.dart';

RandomColor randomColor = RandomColor();

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random(); // Add this line.
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Numbers(),
      debugShowCheckedModeBanner: false,
    );
  }
}

/**
 * View
 */
class Numbers extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return NumbersState();
  }
}

/**
 * Item
 */
class Item extends StatefulWidget {
  int value;

  Item({this.value});

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ItemState();
  }
}

class ItemState extends State<Item> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: randomColor.randomColor(colorBrightness: ColorBrightness.light),
      child: ListTile(
        title: Text(widget.value.toString()),
        onTap: () {
          setState(() {
            widget.value++;
          });
        },
      ),
    );
  }
}

/**
 * List
 */
class NumbersState extends State<Numbers> {
  List<Item> numbers = new List<Item>();
  String message = "Teste";

  void addItem(int v) {

    Item i = Item(value: v,);
    numbers.add(i);
    setState(() {});
  }

  Stream generateNumbers() async* {
    for (int i in List.generate(5, (i) => i)) {
      yield i;
    }
  }

  @override
  void initState() {
//    super.initState();
    generateNumbers().listen((dynamic i) {
      print(i);
      Timer(Duration(seconds: 0), () {
        addItem(i);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Add from here...
      appBar: AppBar(
        title: Text('ListView'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.ac_unit),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_upward),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_downward),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              addItem(1);
            },
          ),
          IconButton(
            icon: Icon(Icons.remove),
            onPressed: () {
              numbers.removeAt(numbers.length-1);
              setState(() {});
            },
          )
        ],
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            padding: EdgeInsets.all(16),
            child: Text("Teste de ListView: \n 1. Atualizar item\n 2. Navegação\n 3. Movimento"),
          ),
          Expanded(
            child: ListView.builder(
              reverse: true,
              itemCount: numbers.length,
              itemBuilder: (context, int i) {
                return numbers[i];
                })
          )
        ],
      ),
    ); // ... to here.
  }
}

If you have a large number of items, it is fast to use setState() with ListView.builder(). For example:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<int> ids = [];
  initState() {
    super.initState();
    for (var i = 0; i < 100; i++) {
      ids.add(i);
    }
    new Future.delayed(Duration(seconds: 3)).then((_) {
      setState(() {
        ids[4] = 1000;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: ListView.builder(
          itemCount: ids.length,
          itemBuilder: (context, idx) {
            return ListTile(title: Text('${ids[idx]}'));
          },
        ),
      ),
    );
  }
}

Check out the ListView.builder docs for more details.