flutter - Flutter Item ExpansionPanelList不会更改状态

标签 flutter dart provider flutter-provider

我正在尝试从API检索数据,效果很好。
之后,我想在通过方法构建的ExpansionPanelList中显示我的数据:

class _CartaPageState extends State<CartaPage> {

  
  @override
  Widget build(BuildContext context) {
    // Nos suscribimos al provider
    final productoService = Provider.of<ProductoService>(context);
    final List<Producto> productos = productoService.productos; 
    _productosItems = productosToItem(productos);
    return Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: ListView(
          children: [
            ExpansionPanelList(
              animationDuration: Duration(milliseconds: 300),
              expansionCallback: (int index, bool isExpanded) {
                setState(() {
                  _productosItems[index].isExpanded = !isExpanded;
                  //productosItems[index].isExpanded = !productosItems[index].isExpanded;
                });
              },
              //children: productosToItem(productoService.entrantes).map<ExpansionPanel>((Item item) {
              children: _productosItems.map<ExpansionPanel>((Item item) {
                return ExpansionPanel(
                  headerBuilder: (context, isExpanded) {
                    return ListTile(
                      title: Text(item.headerValue),
                    );
                  },
      ................
数据显示完美,但是状态不是刷新我的ItemModel上的,我认为问题是因为小部件在每次触摸面板列表时都在重绘,因此从API检索(再次)数据并且从不更改状态。
我该如何解决?
先感谢您
编辑:CartaPage由包装:
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => ProductoService()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Material App',
        home: CartaPage()
      ),
    );
  }
}
编辑2:
我同意我正在失去状态,这是将产品转换为项目的方法:
List<Item> productosToItem(List<Producto> productos) {
  return List.generate(productos.length, (index) {
    return Item(
      headerValue: productos[index].tipo,
      expandedValue: productos[index].nombre,
    );
  });
}

最佳答案

ExpansionPanel是否将其isExpanded设置为item.isExpanded
您可以从生成的isExpanded中获取productosToItem()状态。
当您调用setState时,您将排队等待新的构建,它将再次调用productosToItem()。不知道该方法能做什么,我无济于事。
我建议您调查productosToItem以及为什么它没有将isExpanded设置为正确的值。
如果_productosItems[index].isExpanded不是二传手,我想您会失去状态。
编辑1:
您可以创建一个内部状态列表,以保留扩展状态:

class Item {
  Item({
    this.expandedValue,
    this.headerValue,
    this.producto,
    this.isExpanded = false,
  });

  String expandedValue;
  String headerValue;
  Producto producto; // <------------- ADDED
  bool isExpanded;
}

class _CartaPageState extends State<CartaPage> {
  Map<Producto, bool> expanded = {}; // <------------- ADDED

  @override
  Widget build(BuildContext context) {
    // Nos suscribimos al provider
    final productoService = Provider.of<ProductoService>(context);
    final List<Producto> productos = productoService.productos;
    // NOTE: ----------- converted to a local variable
    final _productosItems = productosToItem(productos);
    return Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: ListView(
          children: [
            ExpansionPanelList(
              key: ValueKey(productos.length),  // <------------- ADDED
              animationDuration: Duration(milliseconds: 300),
              expansionCallback: (int index, bool isExpanded) {
                // NOTE: ----------- updated
                final producto = productos[index];
                setState(() {
                  expanded[producto] = !isExpanded;
                });
              },
              children: _productosItems.map<ExpansionPanel>((Item item) {
                return ExpansionPanel(
                  isExpanded: expanded[item.producto], // <------------- ADDED
                  canTapOnHeader: true,
                  headerBuilder: (context, isExpanded) {
                    return ListTile(
                      title: Text(item.headerValue),
                    );
                  },
                  body: ListTile(
                    title: Text(item.expandedValue),
                  ),
                );
              }).toList(),
            ),
          ],
        ),
      ),
    );
  }

  List<Item> productosToItem(List<Producto> productos) {
    // keep a list of previous map
    final toRemove = Map<Producto, bool>.from(expanded);
    final items = List.generate(productos.length, (index) {
      final producto = productos[index];
      // set initial expanded state
      expanded.putIfAbsent(producto, () => false);
      // the item will be retained
      toRemove.remove(producto);
      return Item(
        headerValue: producto.tipo,
        expandedValue: producto.nombre,
        producto: producto,
        isExpanded: expanded[producto],
      );
    });
    if (toRemove.isNotEmpty) {
      // cleanup unused items
      expanded.removeWhere((key, _) => toRemove.containsKey(key));
    }
    return items;
  }
}
之所以需要key: ValueKey(productos.length),,是因为ExpansionPanelList对出现或消失的物品具有不可思议的作用。

关于flutter - Flutter Item ExpansionPanelList不会更改状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63791454/

相关文章:

flutter - 删除卡之间的空间

dart - 构造函数未在静态属性上调用

flutter - 在没有 BuildContext 的情况下预加载图像

flutter - 当我尝试使用提供程序从 ListView 中删除项目时,它在 flutter 中从列表中删除了最后一个元素

list - 具有自定义列表的IndexOf(Flutter-Dart)

dart - 为什么我的 ListView 没有用 setstate 更新

dart - 如何在 Dart 中初始化 mixin 的不可变数据?

flutter - 单击下拉菜单项后如何显示自定义值

javascript - AngularJS - 错误 : [$injector:pget] Provider 'function ()' must define $get factory method

java - 使用 Java 的 OpenId 提供者/服务器