微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flutter StatefulWidget 没有被重建

如何解决Flutter StatefulWidget 没有被重建

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。