flutter 当父项更新其自身状态时,模态底部工作表不会重新呈现自身

isr3a4wc  于 2023-03-31  发布在  Flutter
关注(0)|答案(1)|浏览(116)

场景及要求:

我想从Repository加载一些字符串。在这个例子中,我们使用**Future.delayed()从本地Repository加载它们。
我们有一个按钮来显示所有名称。这些名称
应该在showModalBottomSheet()**中列出。如果名称尚未加载,showModalBottomSheet()应该显示一个圆形进度指示器。如果名称已加载,showModalBottomSheet()应该显示名称。

问题是

showModalBottomSheet()如果时间小于3秒,则显示循环进度指示器,如果时间大于3秒,则显示名称。BUT,如果我们打开showModalBottomSheet()在3秒过去之前,并保持打开,showModalBottomSheet的内容()应该自动重新渲染,因为名称在3秒后加载,但循环进度指示器永远不会消失,因为底部工作表永远不会触发重新呈现,即使List已经从Repository加载。

代码

我有下面这个最小可重复的例子,编译运行正常:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(title: 'Title', home: Home());
  }
}

class Home extends StatelessWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: HomeBody(),
    );
  }
}

class HomeBody extends StatefulWidget {
  const HomeBody({super.key});

  @override
  State<StatefulWidget> createState() => _HomeBodyState();
}

class _HomeBodyState extends State<HomeBody> {
  final NamesRepository _namesRepository = NamesRepository();

  late List<String> _names;

  @override
  void initState() {
    super.initState();
    _names = [];
    _namesRepository.loadNames().then((names) => setState(() {
          _names = names;
        }));
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      child: const Text('Show all names'),
      onPressed: () => _onButtonClick(context),
    );
  }

  void _onButtonClick(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        if (_names.isEmpty) {
          return const Center(child: CircularProgressIndicator());
        } else {
          return Column(
            children: _names.map((name) => Text(name)).toList(),
          );
        }
      },
    );
  }
}

class NamesRepository {
  Future<List<String>> loadNames() {
    return Future.delayed(
      const Duration(seconds: 3),
      () => ['John', 'Maria', 'Lewis', 'Danny'],
    );
  }
}

我应该怎么做,才能在从Repository加载List时自动重新呈现模态底部工作表?正如你所看到的,我在父Widget中调用了setState(),但是模态底部工作表在状态改变时仍然不会重新呈现自己。我该如何解决这个问题?

0g0grzrc

0g0grzrc1#

usually doing a setState() in Parent widget will not have effect in modelsheet because both use different context.
you try instead,
  void _onButtonClick(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return ModelSheet();
      },
    );
  }

and have ModelSheet as StatefulWidget and do the init method here, it will work.

class _ModelSheetState extends State<ModelSheet> {
  final NamesRepository _namesRepository = NamesRepository();

  late List<String> _names;

  @override
  void initState() {
    super.initState();
    _names = [];
    _namesRepository.loadNames().then((names) => setState(() {
          _names = names;
        }));
  }

  @override
  Widget build(BuildContext context) {
    return if (_names.isEmpty) {
          return const Center(child: CircularProgressIndicator());
        } else {
          return Column(
            children: _names.map((name) => Text(name)).toList(),
          );
        }
  }
}

相关问题