Android 仅重建颤振列表视图中的一行?

Android 仅重建颤振列表视图中的一行?,android,ios,dart,flutter,Android,Ios,Dart,Flutter,我遵循了关于颤振的示例应用程序 并注意到,每次我单击该行(使字对成为收藏夹并在其旁边显示红心),整个listview都会重建。 我认为重建整个列表可能效率低下,所以我修改了示例中的原始代码,以便只有平铺状态发生更改,并认为这将使只有平铺需要重新绘制。我看到状态已更改,但未重新绘制/重建磁贴 现在,我认为它可能没有意义,因为在更新过程中磁贴大小可能会改变,并且无论如何都需要重建listview,但我的问题是: 如果setState()调用按正常方式进行,并且磁贴被标记为脏磁贴,那么到底是什么阻止

我遵循了关于颤振的示例应用程序

并注意到,每次我单击该行(使字对成为收藏夹并在其旁边显示红心),整个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()