SliverChildBuilderDelegate使用setState更改数据时不重建其子级

时间:2020-03-25 16:16:13

标签: flutter dart flutter-layout flutter-sliver

我有一个UI,可以在杂货店应用程序中向用户显示已交付的商品和已取消的商品。

“已交付”->按下此按钮将显示已交付物品卡小部件。

并在同一页面上

“已取消”->按下此按钮将显示已取消的物品卡小部件。

我正在使用SliverChildBuilderDelegate根据用户的当前输入来构建卡片小部件。(最初在加载页面时,我将显示所有已交付的商品。)

SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) => MyOrdersCard(
                  orderNumber: orderList[index][0],
                  trackingNumber: orderList[index][1],
                  quantity: orderList[index][2],
                  totalAmount: orderList[index][3],
                  status: orderList[index][4],
                  date: orderList[index][5],
                  statusColor: orderList[index][6],
                ),
                childCount: orderList.length,
              ),
            ),

我在下面的代码中用具有order状态的status变量填充列表(“ orderList”)。

var orderList = [];

handleClick(status) {

     setState(() {

          orderList = [];

          var color;
          switch (status) {
              case 'Processing':
                color = Colors.yellow;
                activeBtn = 2;
                break;
              case 'Cancelled':
                color = Colors.red;
                activeBtn = 3;
                break;
              case 'Delivered':
                color = Colors.green;
                activeBtn = 1;
                break;
          }
          for (int i = 0; i < 10; i++) {
                  orderList.add([
                    '123457' + '$i',
                    '17abc999',
                    3,
                    500,
                    status,
                    '0$i-12-2019',
                    color
                  ]);
          }

});

按下按钮时,将以状态为参数调用上述函数。

        RaisedButton(
                      child: Text('Delivered'),                      
                      onPressed: () {
                        handleClick('Delivered');
                      },
                    ),
        RaisedButton(
                      child: Text('Processing'),
                      onPressed: () {
                        handleClick('Processing');
                      },
                    ),

现在,UI可以正确显示所有已交付的卡项目,但是如果用户按下“已取消”按钮,则将调用“ handleClick”功能,并且列表中将包含所有新取消的订单,并且状态也会被填充为已取消。但是sliverChildBuilder并没有刷新。用户界面保持不变。如果我在下面滚动,则可以看到已取消的订单,因为它们是在向下滚动时重新生成的。现在,如果我再次向上滚动,则可以看到所有已取消的订单,因为旧的构建卡已被破坏,并且sliverChildBuilder将这些生成的卡构建为滚动发生在飞行中。我不要这个我希望sliverChildBuilder可以在按下“已取消”按钮时销毁为“已交付”物料创建的所有旧子级,并呈现新列表(“ orderList”)中所有已取消的新订单。 有什么办法可以做到吗?希望我的问题解决了!

2 个答案:

答案 0 :(得分:1)

我希望我还不晚。我的回答会很有用。

import 'dart:math' as math;

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: SafeArea(
          child: MyHomePage(),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Order> orderList = [
    Order(status: Status.delivered),
    Order(status: Status.canceled),
    Order(status: Status.delivered),
  ];

  void _showStatus(int index, Status status) {
    setState(() {
      currentStatusToShow = status;
    });
  }

  Status currentStatusToShow = Status.canceled;
  @override
  Widget build(BuildContext context) {
    var showList = orderList
        .where((order) => order.status == currentStatusToShow)
        .toList();
    return CustomScrollView(
      slivers: [
        SliverPadding(
          padding: EdgeInsets.only(bottom: 20, top: 50),
          sliver: SliverToBoxAdapter(
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    RaisedButton(
                      color: Colors.red,
                      onPressed: () => _showStatus(0, Status.canceled),
                      child: Text('Cancel'),
                    ),
                    RaisedButton(
                      color: Colors.green,
                      onPressed: () => _showStatus(0, Status.delivered),
                      child: Text('delivered'),
                    )
                  ],
                )
              ],
            ),
          ),
        ),
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (context, index) => MyOrdersCard(
              order: showList[index],
            ),
            childCount: showList.length,
          ),
        ),
      ],
    );
  }
}

class MyOrdersCard extends StatelessWidget {
  const MyOrdersCard({
    Key key,
    this.order,
    this.changeStatus,
  }) : super(key: key);

  final Order order;
  final void Function(Status) changeStatus;

  Color get color {
    switch (order.status) {
      case Status.processing:
        return Colors.yellow;
      case Status.canceled:
        return Colors.red;
      case Status.delivered:
      default:
        return Colors.green;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      height: 100,
      color: color,
      child: Column(
        children: [
          Text(order.status.toString()),
          SizedBox(height: 20),
          Text(order.orderId)
        ],
      ),
    );
  }
}

enum Status { processing, canceled, delivered }

class Order {
  Order({this.status});
  Status status;

  String orderId = 'SA-${math.Random().nextInt(1040)}';
}

答案 1 :(得分:0)

如果您使用 SliverChildBuilderDelegate,您应该检查 key 的子小部件。

示例:

List<String> data = ['first', 'second'];

SliverList(
    delegate:
        SliverChildBuilderDelegate((context, index) {
            return ChildWidget(data[index], UniqueKey());
        }, childCount: data.length),
);

当您更新数据时,密钥有助于重建子级。

class ChildWidget extends StatelessWidget {
const ChildWidget(this.sourceData, key) : super(key: key);
    final String sourceData;

@override
Widget build(BuildContext context) {
    return Text(sourceData ?? '');
    }
}

如果您需要更多关于按键工作原理的信息,请访问 https://api.flutter.dev/flutter/widgets/GlobalKey-class.htmlhttps://www.youtube.com/watch?v=kn0EOS-ZiIc