Flutter中的ListView动态排序

Posted

技术标签:

【中文标题】Flutter中的ListView动态排序【英文标题】:Sort dynamically ListView in Flutter 【发布时间】:2021-02-05 15:06:06 【问题描述】:

我想根据 BottomNavigationBar 中的 StreamController 对 ListView 进行排序。 问题是当我单击应用栏上的按钮时,Listview 没有刷新。

我想将用户选择的函数(Comparable of Company)作为参数传递。

这是我的代码:

Home.dart

final CompanyService _companyService = CompanyService();
final AuthService _auth = AuthService();

class HomePage extends StatefulWidget 
  HomePage(Key key) : super(key: key);
  Home createState() => Home();


class Home extends State<HomePage> 
  Comparator<Company> _sortFunction;
  int _currentIndex;
  var _tabs = [];

  @override
  void initState() 
    super.initState();
    _currentIndex = 0;

    _sortFunction = (a, b) => a.name.compareTo(b.name);
  

  PreferredSize getDoubleHomeAppBar() 
    return PreferredSize(
        preferredSize: Size.fromHeight(55.0),
        child: Row(
          children: <Widget>[
            Expanded(
              child: Container(
                padding: EdgeInsets.only(left: 12.0),
                margin:
                    const EdgeInsets.only(left: 12.0, bottom: 8.0, right: 12.0),
                color: PRIMARY_COLOR,
              ),
            ),
            FlatButton.icon(
              icon: Icon(Icons.sort_by_alpha),
              label: Text(
                'Sort',
              ),
              onPressed: () 
                setState(() 
                  _sortFunction = (a, b) => b.city.compareTo(a.city);
                  _tabs[0] = CompanyTab(sortFunction: _sortFunction);
                );
              ,
            ),
          ],
        ));
  

  @override
  Widget build(BuildContext context) 

    _tabs = [
      CompanyTab(sortFunction: _sortFunction),
      MapTab(),
      Center(child: Text('Profile')),
      Center(child: Text('Settings')),
    ];

    return Scaffold(
      backgroundColor: BACKGROUND_COLOR,
      appBar: AppBar(
        elevation: 0.0,
        centerTitle: true,
        title: Text(
          'JobAdvisor',
          style: TextStyle(
            fontSize: MediaQuery.of(context).size.height / 24,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
        bottom: _currentIndex == 0 ? getDoubleHomeAppBar() : null,
        actions: <Widget>[...],
      ),
      body: _tabs[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        backgroundColor: BACKGROUND_COLOR,
        type: BottomNavigationBarType.fixed,
        items: [
          ...
        ],
        onTap: (index) 
          setState(() 
            _currentIndex = index;
            print('Index: $index');
            print('Current index: $_currentIndex');
          );
        ,
      ),
    );
  

CompanyTab.dart

@immutable
class CompanyTab extends StatefulWidget 
  final CompanyService _companyService = CompanyService();
  final Comparator<Company> sortFunction;

  CompanyTab(Key key, this.sortFunction) : super(key: key);

  @override
  _CompanyTabState createState() =>
      _CompanyTabState(_companyService, sortFunction);


class _CompanyTabState extends State<CompanyTab> 
  StreamController<List<Company>> _streamController;
  final CompanyService _companyService;
  Comparator<Company> sortFunction;

  _CompanyTabState(this._companyService, this.sortFunction);

  @override
  void initState() 
    super.initState();
  

  StreamBuilder companyList() 
    return StreamBuilder<List<Company>>(
        initialData: [],
        stream: _streamController.stream,
        builder: (BuildContext context, AsyncSnapshot<List<Company>> snapshot) 
          if (snapshot.hasError) 
            return Text("Something went wrong");
          

          if (snapshot.connectionState == ConnectionState.waiting ||
              snapshot.connectionState == ConnectionState.none ||
              snapshot.data == null) 
            return LoadingWidget();
           else 
            return ListView.builder(
                padding: const EdgeInsets.all(10),
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) 
                  Company company = snapshot.data.elementAt(index);

                  ...
                
          
        );
  

  @override
  void dispose() 
    _streamController.close();
    super.dispose();
  

  void _getData() 
    _streamController = new StreamController<List<Company>>();
    _companyService.getCompanies().then((value) => _elaborateList(value));
  

  void _elaborateList(List<Company> list) 
    List<Company> tmp = list;
    tmp.sort(sortFunction);
    print(tmp.toString());
    _streamController.sink.add(tmp);
  

  @override
  Widget build(BuildContext context) 
    _getData();
    return Center(
      child: Container(
        child: companyList(),
      ),
    );
  

【问题讨论】:

【参考方案1】:

我认为问题出在您的排序方法上。应该是这样的:

     _sortFunction.sort((a, b) => a.name.compareTo(b.name));

您可以阅读official document。

编辑:

你需要在这里使用小部件的 sortFunction:

     tmp.sort(widget.sortFunction);

您没有在 CompanyTab 中使用相同的 sortFunction。您应该使用作为参数的 sortFunction。 Here 是关于它的博客。

【讨论】:

这是第一个问题,但公司标签小部件无论如何都不会刷新。 它工作正常。我还必须删除 CompanyTab.dart 中的 Key 键。非常感谢! 好的,现在你可以接受并支持我的回答了 :)

以上是关于Flutter中的ListView动态排序的主要内容,如果未能解决你的问题,请参考以下文章

Flutter ListView 与 List 中的小部件不会在应该更新时更新

Flutter - 另一个 Listview 中的 Listview.builder

flutter listview item滚出屏幕不重置状态

Flutter:如何将 StreamBuilder 与 ListView.separated 一起使用

Flutter:根据类型对 ListView 项进行排序

Flutter Listview 排序动画