【问题标题】:Flutter StatefulWidget is not being rebuildFlutter StatefulWidget 没有被重建
【发布时间】:2021-08-18 06:25:27
【问题描述】:

我在使用这段代码时遇到了一些问题.. 我将我的小部件“ComponentsHistoriqueDeployment”移动到带有 initState() 的 statefulwidget,以解决每次小部件时正在重建的焦点问题。 所以实际上数据是第一次获取的,但是当我在搜索栏“Sélectionnez le composant”中录制某些内容或更改 datePicker 时,它不会改变。

我不明白为什么......

这是父母:

class HistoriquePage extends StatefulWidget {
  final String pageName;
  final String namespace;

  const HistoriquePage({Key? key, required this.pageName, required this.namespace}) : super(key: key);

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

class _HistoriquePageState extends State<HistoriquePage> {
  final _debounce = Debounce();
  DateTimeRange? dateRange;
  String searchedValue = "";
  Post? user;

  void _sendSearch(String value) {
    _debounce.run(() {
      setState(() {
        searchedValue = value;
      });
    });
  }

  @override
  Widget build(BuildContext context) => GestureDetector(
      onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.pageName),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              Container(
                child: DateRangeField(
                    enabled: true,
                    firstDate: new DateTime(2020),
                    helpText: 'Sélectionnez un interval de dates',
                    fieldStartLabelText: 'Date de début',
                    fieldEndLabelText: 'Date de fin',
                    fieldStartHintText: 'Début',
                    fieldEndHintText: 'Fin',
                    dateFormat: DateFormat('dd/MM/yyyy'),
                    saveText: 'OK',
                    decoration: InputDecoration(
                      prefixIcon: Icon(Icons.date_range, color: Theme.of(context).primaryColor),
                      hintText: 'Sélectionnez un intervalle de dates',
                      hintStyle: Theme.of(context).textTheme.headline6,
                      border: OutlineInputBorder(),
                    ),
                    onChanged: (value) {
                      setState(() {
                        dateRange = value!;
                      });
                    }),
              ),
              Container(
                padding: EdgeInsets.all(16),
                child: TextField(
                    decoration: InputDecoration(
                        prefixIcon: Icon(Icons.search, color: Theme.of(context).primaryColor),
                        border: OutlineInputBorder(),
                        labelText: 'Sélectionnez le composant',
                        labelStyle: Theme.of(context).textTheme.headline6),
                    onChanged: _sendSearch),
              ),
              Container(height: MediaQuery.of(context).size.height - 150, child: ComponentsHistoriqueDeployment(searchedValue, dateRange: dateRange))
            ],
          ),
        ),
      ));
}

以及应该重建的小部件:

class ComponentsHistoriqueDeployment extends StatefulWidget {
  ComponentsHistoriqueDeployment(this.searchedValue, {this.dateRange, Key? key}) : super(key: key);

  final String searchedValue;
  final DateTimeRange? dateRange;

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

class ComponentsHistoriqueDeploymentState extends State<ComponentsHistoriqueDeployment> {
  List<User>? listOfGroups;

  @override
  void initState() {
    getGroupsList();
    super.initState();
  }

  getGroupsList() async {
    listOfGroups = await HistoriqueService.fetchHistorique(widget.searchedValue, dateRange: widget.dateRange);
    setState(() {
      listOfGroups = listOfGroups;
    });
  }

  @override
  Widget build(BuildContext context) {
    return listOfGroups == null
        ? Center(child: CircularProgressIndicator())
        : ListView.separated(
            separatorBuilder: (BuildContext context, int index) => const Divider(),
            itemCount: listOfGroups!.length,
            itemBuilder: (context, index) {
              return Card(
                child: Column(children: [
                  Padding(
                    padding: const EdgeInsets.only(top: 8),
                    child: Badge(
                      toAnimate: true,
                      animationDuration: Duration(seconds: 2),
                      shape: BadgeShape.square,
                      badgeColor: Theme.of(context).primaryColor,
                      borderRadius: BorderRadius.circular(8),
                      badgeContent: Text(listOfGroups![index].name, style: TextStyle(color: Specific.getWhite, fontSize: 16)),
                    ),
                  ),
                  _displayMoreInformationOnComponent(listOfGroups, index, context)
                ]),
              );
            });
  }

  Widget _displayMoreInformationOnComponent(result, index, context) {
    return Container(
      child: ListTile(
        title: Text('Tag: ' + result[index].username),
        subtitle: Text('Date: ' + result[index].address.street),
        leading: Icon(Icons.label),
        trailing: Wrap(
          spacing: 20,
          children: <Widget>[
            IconButton(
              icon: Icon(Icons.help),
              onPressed: () => Dialogs.bottomMaterialDialog(
                  msgStyle: TextStyle(color: Theme.of(context).textTheme.bodyText2?.color),
                  msg: 'Tag: ' +
                      result[index].name +
                      '\nStatus: ' +
                      result[index].name +
                      '\nDernier déploiement: ' +
                      result[index].name +
                      '\nType de route: ' +
                      result[index].name +
                      '\nDernier commit par: ' +
                      result[index].name +
                      '\n',
                  title: result[index].name,
                  color: Specific.getOrange,
                  context: context,
                  actions: [
                    IconsButton(
                      text: "OK",
                      iconData: Icons.check_circle,
                      color: Colors.green,
                      textStyle: TextStyle(color: Specific.getWhite),
                      iconColor: Specific.getWhite,
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                    ),
                  ]),
            ),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter widget stateful


    【解决方案1】:

    这是预期的行为:initState() 在小部件初始化期间仅被调用一次。即使属性更改了它们的值,State 对象也不会重新创建,因此不会调用 getGroupsList()

    在这种情况下,我建议您将getGroupsList() 移动到_HistoriquePageState 小部件并在搜索值或日期范围更改时调用它。然后,不要将 searchedValuedateRange 属性传递给 ComponentsHistoriqueDeployment,而是传递 listOfGroups 值。

    这样,您可以确保每次调用 getGroupsList() 并更新 UI。

    【讨论】:

    • 谢谢,这真的很有帮助! ,我刚刚添加了一个带有initState 的方法来获取HistoriquePage 上的组。因为如果不是,它只是改变了调用:)
    • 是的,当然,初始加载必须在initState()中完成,很好。
    猜你喜欢
    • 1970-01-01
    • 2020-12-18
    • 2020-10-01
    • 2020-10-13
    • 2020-04-11
    • 2021-01-13
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多