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

Flutter 列表视图更新不正​​确

如何解决Flutter 列表视图更新不正​​确

我正在使用 Flutter ListView 测试动态行列表,其中在删除所选行后项目未正确显示。后端明智,指定索引处的数据被删除,但 ListView 将无法正确显示。我知道这与 Key 有关系,但经过数小时的反复试验和 Google 搜索,问题仍然无法解决

有什么我错过的吗?以下是我采取的行动过程:

  1. 将 UniqueKey / Key 放在 ListView.Builder 下(例如 Key(_fieldList.length.toString()))。
  2. 将 ObjectKey / ValueKey / Key 放在 dismissible 或我的自定义行小部件下。

详情请参考 GIF。

[Sample screen recording]
https://i.stack.imgur.com/BEy1V.gif

以下是一些代码片段:

编辑屏幕

    class EditFormScreen extends StatefulWidget {
      final CustomForm _customForm;
      final CustomFormBloc _bloc;
    
      EditFormScreen(this._bloc,this._customForm);
    
      static Future<void> show(
          {BuildContext context,CustomFormBloc formBloc,CustomForm form}) async {
        await Navigator.push(
          context,MaterialPageRoute(
            fullscreenDialog: false,builder: (_) => BlocProvider.value(
              value: formBloc,child: EditFormScreen(formBloc,form),),);
      }
    
      @override
      _EditFormScreenState createState() => _EditFormScreenState();
    }
    
    class _EditFormScreenState extends State<EditFormScreen> {
      final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
      List<CustomField> _fieldsList = [];
      CustomForm _form;
    
      @override
      Widget build(BuildContext context) {
        _form = widget._customForm ?? CustomForm();
        return Scaffold(
          appBar: MainAppBar(title: kEditFormScreen),floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),onpressed: _addNewField,body: Container(
            child: FormBuilder(
              key: _fbKey,autovalidateMode: AutovalidateMode.onUserInteraction,child: BlocBuilder<CustomFormBloc,CustomFormState>(
                builder: (context,state) {
                  return SingleChildScrollView(
                    child: Padding(
                      padding: EdgeInsets.all(16.0),child: Column(
                        children: [
                          FormBuilderTextField(
                            name: "title",maxLines: null,style: TextStyle(height: 1.5),decoration: Inputdecoration(labelText: kFormTitleText),valueTransformer: (value) => value.toString().trim(),]..add(
                            _buildCustomFields(),);
                },);
      }
    
      _addNewField() {
        _fieldsList.add(CustomField(fieldIdentifier: Uuid().v4()));
        widget._bloc.add(
          ModifyFieldFormEvent(CustomField(),true),);
      }
    
      Widget _buildCustomFields() => ListView.builder(
            shrinkWrap: true,//key: UniqueKey(),physics: NeverScrollableScrollPhysics(),itemCount: _fieldsList.length,itemBuilder: (context,index) => dismissible(
              //key: Key("field-${_fieldsList[index].fieldIdentifier}"),key: Key(_fieldsList[index].fieldIdentifier),background: Container(
                  alignment: Alignment.centerRight,child: Padding(
                    padding: EdgeInsets.all(8.0),child: Text(
                      "Delete",style: TextStyle(color: Colors.white,fontSize: 18.0),color: Colors.red),direction: dismissDirection.endToStart,confirmdismiss: (direction) async {
                _fieldsList.removeAt(index);
                widget._bloc.add(
                  ModifyFieldFormEvent(CustomField(),);
                return true;
              },child: FieldRow(
                key: Key(_fieldList[index].fieldIdentifier)
                item: _fieldsList[index],index: index,onMenuSelected: (value) => _handleMenuOnSelected(value,index),);
    
      _handleMenuOnSelected(String value,int index) {
        switch (value) {
          case kEditFieldTitle:
            print("Edit field title...");
            break;
          case kEditFieldType:
            print("Edit field type...");
            break;
          case kDeleteField:
            print("Deleted item: ${_fieldsList[index].fieldIdentifier}");
            _fieldsList.removeAt(index);
            widget._bloc.add(
              ModifyFieldFormEvent(CustomField(),);
            break;
          default:
            break;
        }
      }
    }

行小部件

    class FieldRow extends StatefulWidget {
      final CustomField item;
      final int index;
      final Function(String) onMenuSelected;
    
      FieldRow({Key key,this.index,this.onMenuSelected,this.item}) : super(key: key);
    
      @override
      _FieldRowState createState() => _FieldRowState();
    }
    
    class _FieldRowState extends State<FieldRow> {
      @override
      Widget build(BuildContext context) {
        return Row(
          children: [
            Expanded(
              child: FormBuilderTextField(
                name: "field#${widget.index}",decoration: Inputdecoration(
                    border: InputBorder.none,labelText: "${widget.item.fieldIdentifier}"),PopupMenuButton<String>(
              onSelected: widget.onMenuSelected,itemBuilder: (_) => kCustomFieldOptions
                  .map(
                    (option) => PopupMenuItem<String>(
                      child: Text(option),value: option,)
                  .toList(),],);
      }
    

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