首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >颤振FutureBuilder通过重新加载数据刷新所有用户界面

颤振FutureBuilder通过重新加载数据刷新所有用户界面
EN

Stack Overflow用户
提问于 2022-09-16 17:08:18
回答 1查看 54关注 0票数 1

我有一个从API获取数据的FutureBuilder,我将大量地重新加载这些数据,所以FutureBuilder会刷新很多。

我遇到的问题是,每次都会重建整个小部件结构,并且ListViews和卷轴会被重置回原来的位置。我只希望OrderStack被重建到位。这个是可能的吗?如果是的话,怎么做?

代码语言:javascript
运行
复制
class ServingStationScreen extends StatefulWidget {
  const ServingStationScreen({Key? key}) : super(key: key);

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

class ServingStationScreenState extends State<ServingStationScreen> {

  late Future<Map<String, List<Order>>> ordersFuture;
  @override
  void initState() {
    super.initState();
    ordersFuture = getOrders();
  }

  Future<Map<String, List<Order>>> getOrders() async {
    try {
      var orders = (await APIService().getOrders())!;
      return {
        'ordered': orders.where((order) {
          return order.itemsOrdered!.isNotEmpty;
        }).toList(),
        'preparingAndAwaitingCancellation': orders.where((order) {
          return order.itemsPreparingAndAwaitingCancellation!.isNotEmpty;
        }).toList(),
      };
    } catch (e) {
      return Future.error(e);
    }
  }

  final List<String> emptyImages = [
    'assets/svg/barbecue.svg',
    'assets/svg/beer.svg',
    'assets/svg/breakfast.svg',
    'assets/svg/cooking.svg',
    'assets/svg/fresh-drink.svg',
    'assets/svg/ice-cream.svg',
    'assets/svg/mint-tea.svg',
    'assets/svg/pizza.svg',
    'assets/svg/special-event.svg',
    'assets/svg/tea.svg',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Navigation(
        allowBack: false,
        activePage: 'Serving Station',
        restaurantName: 'Test Restaurant',
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 10),
            child: IconButton(
              onPressed: () {
                setState(() {
                  ordersFuture = getOrders();
                });
                // Get.to(() => const ServingStationHistoryScreen());
              },
              icon: const Icon(
                Icons.history_rounded,
                color: Colors.white,
                size: 26.0,
              ),
            ),
          ),
        ],
      ),
      extendBodyBehindAppBar: true,
      backgroundColor: const Color.fromRGBO(21, 21, 32, 1),
      body: FutureBuilder(
        future: ordersFuture,
        builder: (context, snapshot) {
          switch(snapshot.connectionState) {
            case ConnectionState.none:
            case ConnectionState.waiting:
            case ConnectionState.active:
              return const CircularProgressIndicator(
                color: Color.fromRGBO(93, 194, 188, 1),
              );
            case ConnectionState.done:
              if(snapshot.hasError) {
                return Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Container(
                        padding: const EdgeInsets.only(bottom: 100),
                        child: Opacity(
                          opacity: 0.5,
                          child: SvgPicture.asset(
                            'assets/svg/server.svg',
                            height: SizerUtil.deviceType == DeviceType.tablet ? 500 : 200,
                            theme: const SvgTheme(
                              currentColor: Color.fromRGBO(93, 194, 188, 1),
                            ),
                          ),
                        ),
                      ),
                      Text(
                        'Service Unreachable',
                        textAlign: TextAlign.center,
                        style: TextStyle(fontSize: SizerUtil.deviceType == DeviceType.tablet ? 30 : 18, color: Colors.white),
                      ),
                      Text(
                        'Error: ${snapshot.error}',
                        textAlign: TextAlign.center,
                        style: TextStyle(fontSize: SizerUtil.deviceType == DeviceType.tablet ? 15 : 10, color: Colors.red),
                      ),
                    ],
                  ),
                );
              } else {
                final data = snapshot.data as Map<String, List<Order>>;
                return data['preparingAndAwaitingCancellation']!.isNotEmpty || data['ordered']!.isNotEmpty ? SafeArea(
                  bottom: false,
                  child: ListView(
                    shrinkWrap: false,
                    children: [
                      data['preparingAndAwaitingCancellation']!.isNotEmpty ? Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Container(
                            padding: const EdgeInsets.only(top: 20, left: 20, bottom: 20),
                            child: Row(
                              children: [
                                const Text('Current Items',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 30,
                                  ),
                                ),
                                Container(
                                  margin: const EdgeInsets.only(left: 10, right: 10),
                                  padding: const EdgeInsets.only(left: 5, right: 5, top: 2, bottom: 2),
                                  decoration: BoxDecoration(
                                      color: Colors.yellow[200],
                                      border: Border.all(
                                        color: Colors.transparent,
                                      ),
                                      borderRadius: const BorderRadius.all(Radius.circular(20))
                                  ),
                                  child: const Text(
                                    'Preparing',
                                    style: TextStyle(
                                      color: Colors.black,
                                      fontWeight: FontWeight.bold,
                                      fontSize: 15,
                                    ),
                                  ),
                                ),
                                Container(
                                  padding: const EdgeInsets.only(left: 5, right: 5, top: 2, bottom: 2),
                                  decoration: BoxDecoration(
                                      color: Colors.red[200],
                                      border: Border.all(
                                        color: Colors.transparent,
                                      ),
                                      borderRadius: const BorderRadius.all(Radius.circular(20))
                                  ),
                                  child: const Text(
                                    'Awaiting Cancellation',
                                    style: TextStyle(
                                      color: Colors.black,
                                      fontWeight: FontWeight.bold,
                                      fontSize: 15,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                          SingleChildScrollView(
                            scrollDirection: Axis.horizontal,
                            child: SizedBox(
                              width: data['preparingAndAwaitingCancellation']!.length * 500 < 2500 ? data['preparingAndAwaitingCancellation']!.length * 500 : 2500,
                              child: MasonryGridView.count(
                                physics: const NeverScrollableScrollPhysics(),
                                crossAxisCount: data['preparingAndAwaitingCancellation']!.length < 5 ? data['preparingAndAwaitingCancellation']!.length : 5,
                                mainAxisSpacing: 10,
                                crossAxisSpacing: 10,
                                shrinkWrap: true,
                                itemCount: data['preparingAndAwaitingCancellation']!.length,
                                padding: const EdgeInsets.only(left: 20, right: 20),
                                itemBuilder: (context, index) {
                                  return OrderStack(
                                    order: data['preparingAndAwaitingCancellation']![index],
                                    filter: OrderStatusFilter.preparingAndAwaitingCancellation,
                                  );
                                },
                              ),
                            ),
                          ),
                        ],
                      ) : Container(),
                      data['ordered']!.isNotEmpty ? Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Container(
                            padding: const EdgeInsets.only(top: 20, left: 20, bottom: 20),
                            child: Row(
                              children: [
                                const Text('New Items',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 30,
                                  ),
                                ),
                                Container(
                                  margin: const EdgeInsets.only(left: 10, right: 10),
                                  padding: const EdgeInsets.only(left: 5, right: 5, top: 2, bottom: 2),
                                  decoration: BoxDecoration(
                                      color: Colors.white,
                                      border: Border.all(
                                        color: Colors.transparent,
                                      ),
                                      borderRadius: const BorderRadius.all(Radius.circular(20))
                                  ),
                                  child: const Text(
                                    'Ordered',
                                    style: TextStyle(
                                      color: Colors.black,
                                      fontWeight: FontWeight.bold,
                                      fontSize: 15,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                          SingleChildScrollView(
                            scrollDirection: Axis.horizontal,
                            child: SizedBox(
                              width: data['ordered']!.length * 500 < 2500 ? data['ordered']!.length * 500 : 2500,
                              child: MasonryGridView.count(
                                physics: const NeverScrollableScrollPhysics(),
                                crossAxisCount: data['ordered']!.length < 5 ? data['ordered']!.length : 5,
                                mainAxisSpacing: 10,
                                crossAxisSpacing: 10,
                                shrinkWrap: true,
                                itemCount: data['ordered']!.length,
                                padding: const EdgeInsets.only(left: 20, right: 20),
                                itemBuilder: (context, index) {
                                  return OrderStack(
                                    order: data['ordered']![index],
                                    filter: OrderStatusFilter.ordered,
                                  );
                                },
                              ),
                            ),
                          ),
                        ],
                      ) : Container(),
                    ],
                  ),
                ) : Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Container(
                        padding: const EdgeInsets.only(bottom: 100),
                        child: Opacity(
                          opacity: 0.5,
                          child: SvgPicture.asset(
                            emptyImages.elementAt(Random().nextInt(emptyImages.length)),
                            height: SizerUtil.deviceType == DeviceType.tablet ? 500 : 200,
                            theme: const SvgTheme(
                              currentColor: Color.fromRGBO(93, 194, 188, 1),
                            ),
                          ),
                        ),
                      ),
                      Text(
                        'There are currently no pending orders.',
                        textAlign: TextAlign.center,
                        style: TextStyle(fontSize: SizerUtil.deviceType == DeviceType.tablet ? 30 : 18, color: Colors.white),
                      ),
                    ],
                  ),
                );
              }
          }
        },
      ),
    );
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-17 04:30:10

您应该尽可能地将您的FutureBuilder放到小部件树中,只包装受该未来影响的小部件。看起来,您有一个包含SingleChildScrollViewOrderStack,所以您可能只在FutureBuilder中包装这个小部件。然后,当ordersFuture完成时,只更新UI的这一部分。

另外,如果这本质上是一个数据流,那么考虑使用StreamBuilder - FutureBuilder通常用于等待一次任务的完成(例如,将数据加载到列表中),而不一定要刷新它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73748236

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档