如何更新颤动列表中的单个项目?
我需要最好的方法。
为什么我说最好的方法?
我需要更新单个项目,并且当列表上所有项目都存在时,我不希望更新单个项目。
我的意思是,更新单个项目时,仅刷新那个项目而不是整个列表。
因为如果整个列表都只用于更新一项而被渲染,那么到那时我们的应用程序可能无法获得良好的性能。
那么有办法克服这个问题吗?
答案 0 :(得分:8)
这是我的方式
foods[foods.indexWhere((element) => element.uid == food.uid)] = food;
应进行一些验证,以避免出现空引用问题
答案 1 :(得分:0)
如果您有大量项目,则将setState()与ListView.builder()一起使用会很快。例如:
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]}'));
},
),
),
);
}
}
查看ListView.builder docs以获得更多详细信息。
答案 2 :(得分:0)
您可以通过在每个项目构建器中嵌套流构建器来实现。
这可以通过使用流构建器的initialData
参数来实现。
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)
);
}
)
但是,您可能要对此进行基准测试并将其与更新整个列表进行比较,因为flutter在所有情况下都会重用元素,并且流可能只会带来更多开销。
答案 3 :(得分:0)
我用一个全状态的小部件解决了这个问题,该小部件在ListView中表示一个项目。如果您只想操作项目数据,则可以通过“项目”小部件进行操作。如果您在列表的尾部添加或删除项目,则列表不会重新呈现。
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.
}
}
答案 4 :(得分:0)
如果您知道索引,那么您可以轻松更改其对应项的值。如果您不知道索引,则首先使用 indexOf(E element, [int start = 0])
方法从值中获取索引。然后更改值如下..
List<int> list = [1, 2];
growableList[0] = 87;