Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 625 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to update a single item in flutter list, as a best way

#1
How to update a single item in flutter list?

I need best way.

Why I am saying best way?

I need to update a single item and dont want when update a single item on that all items exists in the list get rendered.

I mean when update a single item, then just that single item should be refreshed not the entire list.

because if the entire list gets render for updating just one item, on that time our app may does not have a good performance.

So is there a way to overcome this?
Reply

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

```dart
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](

[To see links please register here]

) for more details.
Reply

#3
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.
Reply

#4
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.
}
}
Reply

#5
This is my way

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

some validation should be applied to avoid any null reference issues
Reply

#6
If you the know the index then you easily change the value of its corresponding item.. If you don't know the index then first get the index from the value by using `indexOf(E element, [int start = 0])` method. Then change the value as follows..

List<int> list = [1, 2];
growableList[0] = 87;
Reply

#7
simple way is list[index]=updatevalue
Reply

#8
If you make sure that list contains your target.
```
foods.firstWhere((element) => element.id == searchedId) = food;
```
```
foods[foods.indexWhere((element) => element.uid == food.uid)] = food;
```
If you aren't sure.
```
for (int i = 0; i < foods.length; i++) {
if (foods[i].id != searchedId) continue;
foods[i] = food;
break;
}
```

Warning, the `firstWhere` and `indexWhere` can make an error if your target doesn't exist.
or using it before you use these solutions.
```
bool found = foods.contains((food) => food.id == newFood.id);
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through