dart 如何更新一个单一的项目在Flutter名单,作为一个最好的办法

lvjbypge  于 2023-05-04  发布在  Flutter
关注(0)|答案(8)|浏览(180)

如何更新Flutter列表中的单个项目?
我需要最好的方法。
为什么我说最好的方法?
我需要更新一个单一的项目,不希望当更新一个单一的项目上,所有项目存在于列表中得到渲染。
我的意思是,当更新一个项目时,只刷新该项目,而不是整个列表。
因为如果整个列表只更新了一个项目,那么我们的应用程序可能不会有很好的性能。
那么,有没有办法克服这一点呢?

9w11ddsr

9w11ddsr1#

这是我的方式

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

应该应用一些验证来避免任何空引用问题

cwxwcias

cwxwcias2#

您可以通过在每个项生成器中嵌套流生成器来实现此目的。这可以通过使用流构建器的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在所有情况下都会重用元素,而流可能会带来更多开销。

8xiog9wr

8xiog9wr3#

如果您有大量的项,那么将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以了解更多详细信息。

lnlaulya

lnlaulya4#

我用一个statefull小部件来表示ListView中的一个项,从而解决了这个问题。如果您只想操作一个项目数据,您可以通过Item小部件来完成。如果你在列表的尾部添加或删除一个项目,列表将不会被重新呈现。

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.
  }
}
vxbzzdmp

vxbzzdmp5#

您可以使用这种易于阅读的优化方式访问对象:

foods.firstWhere((element) => element.id == searchedId) = food;

而不是这个

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

b0zn9rqh6#

如果你知道索引,那么你可以很容易地改变其相应项的值。如果你不知道索引,那么首先使用indexOf(E element, [int start = 0])方法从值中获取索引。然后按如下方式更改该值。

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

hujrc8aj7#

一个简单的方法是list[index]=updatevalue

cclgggtu

cclgggtu8#

如果你确定名单上有你的目标。

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

如果你不确定。

for (int i = 0; i < foods.length; i++) {
  if (foods[i].id != searchedId) continue;
    foods[i] = food;
    break;
}

警告,如果您的目标不存在,firstWhereindexWhere可能会出错。或在使用这些溶液之前使用它。

bool found = foods.contains((food) => food.id == newFood.id);

相关问题