簡體   English   中英

在Flutter ListView中僅重建一行?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM