【问题标题】:How to filter list when use FutureBuilder?使用 FutureBuilder 时如何过滤列表?
【发布时间】:2020-12-31 01:27:08
【问题描述】:

我在 IndexedListView 中使用 FutureBuilder 来显示电话簿列表,

Widget _buildBody(context) {
  String url = api_url_phonebook;
  return Padding(
    padding: const EdgeInsets.symmetric(horizontal: 10.0),
    child: Column(
      children: [
        TextField(
          onTap: () => onTextChanged(_controller.text),
          ...
        ),
        Expanded(
          child: IndexedListView(
            100.0,
            _getData(context, url),
            ...
          ),
        ),
      ],
    ),
  );
}

Future<Either<ResponseError, List<dynamic>>> _getData(context, url) {
  final result = RequestApi(url).fetchList();
  return result;
}

onSearchTextChanged(String text) {
  ...
}

现在我想在 TextField 中输入文本时过滤此电话簿,我该怎么办?

【问题讨论】:

  • 您的构建方法每次构建时都会调用 API?
  • 能把整个页面的代码放上去吗?将获取的列表结果声明为父小部件中的局部变量。在initState期间获取数据并过滤本地List而不是每次都获取它

标签: flutter textfield flutter-futurebuilder


【解决方案1】:

我建议你使用委托模式来做到这一点。

创建一个如下所示的类:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:mywallet/model/user_account.dart';
import 'package:mywallet/ui/account_item.dart';

class AccountListSearch extends SearchDelegate {
  final List<UserAccount> newItems;
  String selectedResult = '';
  AccountListSearch(this.newItems);

  bool _match(UserAccount account, String text) {
    return account.name.toLowerCase().contains(text.toLowerCase()) ||
        account.user.toLowerCase().contains(text.toLowerCase());
  }

  @override
  List<Widget> buildActions(BuildContext context) => [
        IconButton(
          icon: Icon(Icons.close),
          onPressed: () {
            query = '';
          },
        ),
      ];

  @override
  Widget buildLeading(BuildContext context) => IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          Navigator.pop(context);
        },
      );

  @override
  Widget buildResults(BuildContext context) {
    return Container(
        child: Center(
      child: Text(selectedResult),
    ));
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    var suggestionList = <UserAccount>[];
    query.isEmpty
        ? suggestionList = newItems
        : suggestionList.addAll(
            newItems.where((item) {
              return _match(item, query);
            }),
          );
    return ListView.builder(
      itemCount: suggestionList.length,
      itemBuilder: (context, index) => AccountItem(
        account: suggestionList[index],
      ),
    );
  }
}

复制并粘贴 AccountListSearch 类,仅将 UserAccount 类更改为您的数据类(PhoneBook 项),并使用用于显示您的电话簿项的 Widget 更改 AccountItem 无状态小部件(类似 PhoneBookItemWidget 类扩展 StatelessWidget.... ..)

然后在这个类的主页面中:

class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AccountCubit, AccountState>(
      builder: (_, state) {
        var currentState = state;
        if (currentState is InitializedState) {
          var accounts = currentState.userAccounts;
          return Scaffold(
              appBar: AppBar(
                title: Text('All Accounts'),
                actions: [
                  IconButton(
                    onPressed: () {
                      showSearch(
                          context: context,
                          delegate: AccountListSearch(accounts));
                    },
                    icon: Icon(
                      Icons.search,
                    ),
                  )
                ],
              ),
              drawer: AppDrawer(),
              body:    
              ListView.builder(
                       itemCount: accounts.length,
                      itemBuilder: (context, counter) => AccountItem(
                                               account: accounts[counter],
                                               )
....
}

如您所见,“魔法”在方法中:

showSearch( context: context,  delegate: AccountListSearch(accounts));

方法 showSearch(...) 继承自 StatelessWidget 并为您完成所有工作。

我使用了Bloc模式,但现在并不重要,只是告诉在哪里可以找到项目列表,但它与您的问题没有直接关系。

【讨论】:

  • 所以在你的代码中有两个地方可以调用 AccountItem?一个用于初始,另一个用于搜索?
  • 是的,因为当你过滤它时使用委托类
  • 事实上,您可以使用 Bloc 模式而不是 FutureBuilder 来构建您的小部件。您可以使用“UnitializedState”和“InitializedState”,第一个将运行加载,您可以显示一个 CircularProgressIndicator,最后您切换到 InitializedState,您可以显示上面的小部件。
  • 我终于得到了我需要的东西。我没有使用 SearchDelegate,因为它显示搜索框与列表不在同一页面中。
猜你喜欢
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多