I followed example app on Flutter https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#0
and noticed that every time i click the row (make wordpair favourite and display red heart next to it) whole listview rebuilds. Thought it might be inefficient to rebuild whole list so i modified original code from the example so that only the tile state changes and thought that would make only the tile to be redrawn. I see the state changes but the tile is not being redrawn/rebuild
Now as i think of it it might have no sense as the tile size might change during update and it would require listview to be rebuild anyway but my questions is:
What exactly prevents the tile from being rebuild/redrawn if setState() call proceed as normal and the tile is being marked as dirty?
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);
},
);
}
}
RandomWordsState, but you are callingsetState()inMyListTile. - alex kucksdorf