如何更新颤动列表中的单个项目,这是最佳方法

时间:2019-05-23 22:55:56

标签: dart flutter

如何更新颤动列表中的单个项目?

我需要最好的方法。

为什么我说最好的方法?

我需要更新单个项目,并且当列表上所有项目都存在时,我不希望更新单个项目。

我的意思是,更新单个项目时,仅刷新那个项目而不是整个列表。

因为如果整个列表都只用于更新一项而被渲染,那么到那时我们的应用程序可能无法获得良好的性能。

那么有办法克服这个问题吗?

5 个答案:

答案 0 :(得分:8)

这是我的方式

foods[foods.indexWhere((element) => element.uid == food.uid)] = food;

应进行一些验证,以避免出现空引用问题

答案 1 :(得分:0)

如果您有大量项目,则将setState()与ListView.builder()一起使用会很快。例如:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<int> ids = [];
  initState() {
    super.initState();
    for (var i = 0; i < 100; i++) {
      ids.add(i);
    }
    new Future.delayed(Duration(seconds: 3)).then((_) {
      setState(() {
        ids[4] = 1000;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: ListView.builder(
          itemCount: ids.length,
          itemBuilder: (context, idx) {
            return ListTile(title: Text('${ids[idx]}'));
          },
        ),
      ),
    );
  }
}

查看ListView.builder docs以获得更多详细信息。

答案 2 :(得分:0)

您可以通过在每个项目构建器中嵌套流构建器来实现。 这可以通过使用流构建器的initialData参数来实现。

final Stream<Item> updateItemsSteram = ...;
final List<Item> initialList = [...];
ListView.builder(
  itemBuilder: (context, idx) {
            return StreamBuilder<Item>(
                initialData: initialList[idx],
                stream: updateItemsSteram.where((item) => item.id == initialList[idx].id),
                builder: (ctx, snapshot) => MyCustomWidget(snapshot.data)
             );
          }
)

但是,您可能要对此进行基准测试并将其与更新整个列表进行比较,因为flutter在所有情况下都会重用元素,并且流可能只会带来更多开销。

答案 3 :(得分:0)

我用一个全状态的小部件解决了这个问题,该小部件在ListView中表示一个项目。如果您只想操作项目数据,则可以通过“项目”小部件进行操作。如果您在列表的尾部添加或删除项目,则列表不会重新呈现。

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
import 'package:random_color/random_color.dart';

RandomColor randomColor = RandomColor();

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random(); // Add this line.
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Numbers(),
      debugShowCheckedModeBanner: false,
    );
  }
}

/**
 * View
 */
class Numbers extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return NumbersState();
  }
}

/**
 * Item
 */
class Item extends StatefulWidget {
  int value;

  Item({this.value});

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ItemState();
  }
}

class ItemState extends State<Item> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: randomColor.randomColor(colorBrightness: ColorBrightness.light),
      child: ListTile(
        title: Text(widget.value.toString()),
        onTap: () {
          setState(() {
            widget.value++;
          });
        },
      ),
    );
  }
}

/**
 * List
 */
class NumbersState extends State<Numbers> {
  List<Item> numbers = new List<Item>();
  String message = "Teste";

  void addItem(int v) {

    Item i = Item(value: v,);
    numbers.add(i);
    setState(() {});
  }

  Stream generateNumbers() async* {
    for (int i in List.generate(5, (i) => i)) {
      yield i;
    }
  }

  @override
  void initState() {
//    super.initState();
    generateNumbers().listen((dynamic i) {
      print(i);
      Timer(Duration(seconds: 0), () {
        addItem(i);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Add from here...
      appBar: AppBar(
        title: Text('ListView'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.ac_unit),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_upward),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_downward),
            onPressed: () {
              setState(() {
                message = "Teste";
              });
            },
          ),
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              addItem(1);
            },
          ),
          IconButton(
            icon: Icon(Icons.remove),
            onPressed: () {
              numbers.removeAt(numbers.length-1);
              setState(() {});
            },
          )
        ],
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            padding: EdgeInsets.all(16),
            child: Text("Teste de ListView: \n 1. Atualizar item\n 2. Navegação\n 3. Movimento"),
          ),
          Expanded(
            child: ListView.builder(
              reverse: true,
              itemCount: numbers.length,
              itemBuilder: (context, int i) {
                return numbers[i];
                })
          )
        ],
      ),
    ); // ... to here.
  }
}

答案 4 :(得分:0)

如果您知道索引,那么您可以轻松更改其对应项的值。如果您不知道索引,则首先使用 indexOf(E element, [int start = 0]) 方法从值中获取索引。然后更改值如下..

List<int> list = [1, 2];
growableList[0] = 87;