[英]Rebuilding only one row in Flutter ListView?
我在Flutter上關注了示例應用程序https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#0
並注意到,每當我單擊該行(使wordpair成為收藏夾並在其旁邊顯示紅色的心)時,整個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);
},
);
}
}
在此示例中,您將選定的圖塊保存在_saved
,因此它將更改整個RandomWordsState
。 但是,如果您不需要這樣的東西,則可以避免刷新整個列表
問題很簡單,我應該立即注意到這一點。 isSaved
變量未反映_saved
狀態。 它是在對象創建期間初始化的,僅此而已。 所以當_saved
狀態正在更新isSaved
不得不仍然初始值。 我已經解決了它,當MyListTileState
build()
方法時,該函數放置了一個返回當前單詞對狀態的函數。
事實證明,即使您更改元素的大小,您也可以在ListView
僅重建一個元素而沒有任何問題。 完美運作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.