Android 仅重建颤振列表视图中的一行?
我遵循了关于颤振的示例应用程序 并注意到,每次我单击该行(使字对成为收藏夹并在其旁边显示红心),整个listview都会重建。 我认为重建整个列表可能效率低下,所以我修改了示例中的原始代码,以便只有平铺状态发生更改,并认为这将使只有平铺需要重新绘制。我看到状态已更改,但未重新绘制/重建磁贴 现在,我认为它可能没有意义,因为在更新过程中磁贴大小可能会改变,并且无论如何都需要重建listview,但我的问题是: 如果setState()调用按正常方式进行,并且磁贴被标记为脏磁贴,那么到底是什么阻止了磁贴的重建/重绘Android 仅重建颤振列表视图中的一行?,android,ios,dart,flutter,Android,Ios,Dart,Flutter,我遵循了关于颤振的示例应用程序 并注意到,每次我单击该行(使字对成为收藏夹并在其旁边显示红心),整个listview都会重建。 我认为重建整个列表可能效率低下,所以我修改了示例中的原始代码,以便只有平铺状态发生更改,并认为这将使只有平铺需要重新绘制。我看到状态已更改,但未重新绘制/重建磁贴 现在,我认为它可能没有意义,因为在更新过程中磁贴大小可能会改变,并且无论如何都需要重建listview,但我的问题是: 如果setState()调用按正常方式进行,并且磁贴被标记为脏磁贴,那么到底是什么阻止
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: "This is the title of the App",
home: RandomWords(),
);
}
}
class RandomWordsState extends State<RandomWords> {
final List<WordPair> _suggestions = <WordPair>[];
final Set<WordPair> _saved = Set<WordPair>();
@override
Widget build(BuildContext context) {
print("dupa scaffold");
return new Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
print("dupa listview");
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: (BuildContext _context, int i) {
if (i.isOdd) {
return new Divider();
}
final int index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
},
);
}
Widget _buildRow(WordPair wordPair) {
print ("build row");
return MyListTile(wordPair, _saved.contains(wordPair), () {
print("$wordPair is saved ${_saved.contains(wordPair)}");
final isSaved = _saved.contains(wordPair);
isSaved ? _saved.remove(wordPair) : _saved.add(wordPair);
});
}
}
class MyListTile extends StatefulWidget {
final MyListTileState _state;
MyListTile(WordPair wordPair, bool isSaved, Function stateChangeOnTap):
_state = MyListTileState(wordPair, isSaved, stateChangeOnTap);
@override
State<StatefulWidget> createState() => _state;
}
class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => new RandomWordsState();
}
class MyListTileState extends State<MyListTile> {
final TextStyle _biggerFont = const TextStyle(fontSize: 18.0);
WordPair wordPair;
bool isSaved;
Function stateChangeOnTap;
MyListTileState(this.wordPair, this.isSaved, this.stateChangeOnTap);
@override
Widget build(BuildContext context) {
// TODO: implement build
return new ListTile(
title: Text(
wordPair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
isSaved ? Icons.favorite : Icons.favorite_border,
color: isSaved ? Colors.red : null,
),
onTap: () {
setState(stateChangeOnTap);
},
);
}
}
导入“包装:颤振/材料.省道”;
导入“package:english_words/english_words.dart”;
void main()=>runApp(新的MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
标题:“这是应用程序的标题”,
home:RandomWords(),
);
}
}
类RandomWordsState扩展状态{
最终清单_建议=[];
最终集_saved=Set();
@凌驾
小部件构建(构建上下文){
印刷品(“杜帕脚手架”);
归还新脚手架(
appBar:appBar(
标题:文本(“启动名称生成器”),
),
正文:_buildSuggestions(),
);
}
小部件_buildSuggestions(){
打印(“dupa列表视图”);
返回ListView.builder(
填充:常数边集全部(16.0),
itemBuilder:(BuildContext\u context,int i){
如果(i.isOdd){
返回新的分隔符();
}
最终int指数=i~/2;
如果(索引>=\u建议长度){
_建议.addAll(generateWordPairs().take(10));
}
返回_buildRow(_建议[索引]);
},
);
}
小部件构建行(字对字对){
打印(“生成行”);
返回MyListTile(字对,\ u已保存。包含(字对),(){
打印($wordPair已保存${u saved.contains(wordPair)});
最终isSaved=_saved.contains(字对);
是否保存?\保存。删除(字对):\保存。添加(字对);
});
}
}
类MyListTile扩展StatefulWidget{
最终MyListTil地产(州);
MyListTile(字对字对、布尔保存、函数状态更改映射):
_state=MyListIleState(字对、isSaved、stateChangeOnTap);
@凌驾
状态createState()=>\u状态;
}
类RandomWords扩展了StatefulWidget{
@凌驾
RandomWordsState createState()=>新的RandomWordsState();
}
类MyListTileState扩展了状态{
最终文本样式_biggerFont=常量文本样式(fontSize:18.0);
字对字对;
布尔被保存;
函数stateChangeOnTap;
MyListIlEstate(this.wordPair、this.isSaved、this.stateChangeOnTap);
@凌驾
小部件构建(构建上下文){
//TODO:实现构建
返回新的ListTile(
标题:正文(
wordPair.asPascalCase,
风格:_biggerFont,
),
尾随:新图标(
isSaved?Icons.favorite:Icons.favorite_边框,
颜色:isSaved?颜色。红色:空,
),
onTap:(){
设置状态(stateChangeOnTap);
},
);
}
}
在本例中,您将选定的磁贴保存在\u saved
中,因此它会更改整个随机字状态。但是如果你不需要这些东西,你可以避免刷新整个列表,问题很简单,我应该马上注意到<代码>isSaved
变量未反映\u saved
状态。它是在对象创建过程中初始化的,就是这样。因此,在更新\u saved
状态时,isSaved
仍具有初始值。我已经解决了这个问题,在调用MyListTileState
build()
方法时,在那里放置了一个返回当前字对状态的函数
事实证明,即使更改元素的大小,也可以在
ListView
中重建单个元素,而不会出现任何问题。工作完美 我认为问题在于您试图更新RandomWordsState
的状态,但您正在MyListTile
中调用setState()
。