Flutter StatefulWidget 未重建

Flutter StatefulWidget is not being rebuild

我在使用这段代码时遇到了一些问题.. 我将我的小部件“ComponentsHistoriqueDeployment”移动到带有 initState() 的有状态小部件,以解决每次小部件重建时焦点的一些问题。 所以实际上数据是第一次获取,但当我在搜索栏“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();
                      },
                    ),
                  ]),
            ),
          ],
        ),
      ),
    );
  }
}

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

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

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