Skip to content

child updates every time when clicking on the LiquidPullToRefreshΒ #78

@NooRMaseR

Description

@NooRMaseR

Describe the bug
the LiquidPullToRefresh is supposed to update only when the user Pull not when the user clicks, this causes performance issues

To Reproduce
here's the code I use for home_page.dart

class _AccountsPageState extends State<AccountsPage> {
  final Sql db = Sql();
  late Future<List<Account>> _futuredAccounts;
  final FocusNode _searchBarFocus = FocusNode();
  final TextEditingController _searchController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _futuredAccounts = getData();
    _searchController.addListener(() => setState(() {}));
  }

  Future<List<Account>> getData() async {
    AccountsState accountsState = Provider.of<AccountsState>(context, listen: false);
    accountsState.accounts.clear();
    Provider.of<CurrentExpandedAccount>(context, listen: false).currentAccountID = null;
    List<Map<String, Object?>> accountsFound = await db.getAccount('SELECT * FROM "accounts"');

    if (mounted) {
      accountsState
          ..addManyAccount(accountsFound.map((account) => Account.fromObject(account)).toList())
          ..accountsState.filterdAccounts = accountsState.accounts;
    }

    return accountsState.filterdAccounts;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LiquidPullToRefresh(
        height: 160,
        springAnimationDurationInMilliseconds: 700,
        color: Theme.of(context).brightness == Brightness.dark
            ? const Color.fromARGB(255, 62, 66, 64)
            : Theme.of(context).colorScheme.primary,
        backgroundColor: Colors.white,
        onRefresh: getData,
        child: Column(
          children: [
            CustomAppbar(
              child: Column(
                children: [
                  const SizedBox(
                    height: 35,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const SizedBox(
                        width: 40,
                      ),
                      Text(
                        "appbar_title".tr(),
                        style: const TextStyle(
                            fontSize: 25,
                            fontWeight: FontWeight.bold,
                            color: Colors.white),
                      ),
                      IconButton(
                          onPressed: () => Navigator.of(context).push(
                              CupertinoPageRoute(
                                  builder: (context) => SettingsPage())),
                          icon: const Icon(
                            Icons.settings_outlined,
                            color: Colors.white,
                          )),
                    ],
                  ),
                  const SizedBox(height: 5),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 10),
                    child: Selector<SearchByState, String>(
                      selector: (context, state) => state.searchBy,
                      builder: (context, searchBy, child) => SearchBar(
                        controller: _searchController,
                        focusNode: _searchBarFocus,
                        leading: const Icon(Icons.search),
                        trailing: _searchController.text.isEmpty
                            ? null
                            : <Widget>[
                                IconButton(
                                    onPressed: () {
                                      _searchController.clear();
                                      _searchBarFocus.previousFocus();
                                      AccountsState accountsState =
                                          Provider.of<AccountsState>(context,
                                              listen: false);
                                      accountsState.filterdAccounts =
                                          accountsState.accounts;
                                    },
                                    icon: const Icon(Icons.close_rounded))
                              ],
                        hintText: "search".tr(),
                        onChanged: (value) => _setAccounts(value, searchBy),
                        onTapOutside: (event) =>
                            _searchBarFocus.previousFocus(),
                      ),
                    ),
                  )
                ],
              ),
            ),
            Selector<AccountsState, bool>(
                selector: (context, state) => state.doRefresh,
                builder: (context, shouldRefresh, child) {
                  if (shouldRefresh) {
                    _futuredAccounts = getData();
                    Provider.of<AccountsState>(context, listen: false)
                        .doRefresh = false;
                  }
                  return FutureBuilder(
                      future: _futuredAccounts,
                      builder: (context, snapshot) {
                        print("future changed");
                        if (snapshot.connectionState ==
                            ConnectionState.waiting) {
                          return Expanded(
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                Center(
                                    child: Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    Text("loading".tr()),
                                    const SizedBox(width: 20),
                                    const CircularProgressIndicator(),
                                  ],
                                )),
                              ],
                            ),
                          );
                        } else if (snapshot.hasError) {
                          return Expanded(
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Center(
                                    child: Text(
                                        "${"error".tr()} ${snapshot.error}")),
                              ],
                            ),
                          );
                        } else if (snapshot.data!.isEmpty) {
                          return Expanded(
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Center(child: Text("when_no_accounts".tr())),
                              ],
                            ),
                          );
                        } else {
                          print("has data");
                          return Selector<AccountsState, List<Account>>(
                              selector: (context, state) => state.filterdAccounts,
                              builder: (context, accounts, child) {
                                print("changed");
                                return Expanded(
                                  child: ListView.builder(
                                      itemCount: accounts.length,
                                      itemBuilder: (context, index) => Selector<AccountSecurity, bool>(
                                              selector: (context, state) => state.isDetailsHidden,
                                              builder: (context, isDetailsHidden, child) => AccountCard(
                                                      accountSecurityEnabled: isDetailsHidden,
                                                      account:  accounts[index]
                                              )
                                       )
                                    ),
                                );
                              });
                        }
                      });
                }),
          ],
        ),
      ),
    );
  }
}

Expected behavior
like I said, onPull, it refreshes the child, also when click it refreshes again

Flutter:

  • 3.27.4
  • channel stable

Dart:

  • 3.6.2

Additional context
can anyone please let me know if there's a solution for this

and thanks for your efforts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions