Flutter 避免在 collapsing/expanding ExpansionPanelList 上重建小部件

Flutter avoid widget rebuild on collapsing/expanding ExpansionPanelList

ExpansionPanelList 中,我在 expand/collapse 时遇到重建小部件的问题。

问题出在这里:

expansionCallback: (int index, bool isExpanded) {
  setState(() {
    _profileExpansionStateMap[_profileExpansionStateMap.keys.toList()[index]] = !isExpanded;
  });
},

我将其更改为使用 Bloc 状态管理来解决,但这与 setState() 具有相同的行为。有什么办法可以避免重建小部件树吗?我不能使用 Selector 小部件,因为我认为它在这里对我没有帮助。

import 'package:flutter/material.dart';
void main()=>runApp(MaterialApp(home: Home(),));

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() =>HomeState();

}

class HomeState extends State<Home> {
  Map<String, bool> _profileExpansionStateMap = Map<String, bool>();

  @override
  void initState() {
    super.initState();
    _profileExpansionStateMap = {
      "UserInformation": false,
      "UserWeight": false,
      "UserGeneralInformation": false,
    };
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:Text('ExpansionPanel')),
      body: SingleChildScrollView(
        child: Container(
          padding: EdgeInsets.all(20.0),
          child:ExpansionPanelList(
            expansionCallback: (int index, bool isExpanded) {
              setState(() {
                _profileExpansionStateMap[_profileExpansionStateMap.keys.toList()[index]] = !isExpanded;
              });
            },
            children: <ExpansionPanel>[
              ExpansionPanel(
                  headerBuilder: (BuildContext context, bool isExpanded) {
                    return Container(
                      height: 80.0,
                      child: Text('aaaaaaaa'),
                    );
                  },
                  body: Container(child:Text('aaaaaaaa')),
                  isExpanded: _profileExpansionStateMap["UserInformation"]),
              ExpansionPanel(
                  headerBuilder: (BuildContext context, bool isExpanded) {
                    return Container(
                      height: 80.0,
                      child: Text('bbbbbbbbbbbb'),
                    );
                  },
                  body: Container(child:Text('bbbbbbbbbbbb')),
                  isExpanded: _profileExpansionStateMap["UserWeight"]),
              ExpansionPanel(
                  headerBuilder: (BuildContext context, bool isExpanded) {
                    return Container(
                      height: 80.0,
                      child: Text('ccccccccc'),
                    );
                  },
                  body: Container(child:Text('ccccccccc')),
                  isExpanded: _profileExpansionStateMap["UserGeneralInformation"]),
            ],
          )
        ),
      ),
    );
  }
}

ExpansionPanelList.expansionCallback(...) 是一种方法,只要您点击 ExpansionPanelList 到 expand/collapse 中的箭头按钮,就会调用该方法。

在这种方法中,您实际上应该设置传递给 ExpansionPanelisExpandedbool 值,因此需要您调用 setState(...)

但是,如果您对此有疑问,那么它清楚地表明您的代码有问题。因此,无需避免重建小部件状态。