aagarwal1012 / Liquid-Pull-To-Refresh

🔁 A custom refresh indicator for flutter.

Home Page:https://pub.dev/packages/liquid_pull_to_refresh

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

I do not know if it is a bug, but my key is not working

ceopaludetto opened this issue · comments

When I use a global key, the currentState is always null.

Even if it were in class scope or inside the BlocBuilder the return is null, would it be a BlocBuilder problem? Or is it my mistake?

Normal RefreshIndicators also do not work.

Thanks for listening.

My reproduction:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:autocomplete_textfield/autocomplete_textfield.dart';
import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart';

import 'package:genesis/bloc/models/user.dart';
import 'package:genesis/bloc/controllers/index.dart';

class SelectClient extends StatefulWidget {
  final User defaultUser;

  SelectClient({Key key, this.defaultUser}) : super(key: key);

  _SelectClientState createState() => _SelectClientState();
}

class _SelectClientState extends State<SelectClient> {
  final GlobalKey<AutoCompleteTextFieldState<User>> _autoCompleteKey =
      GlobalKey();

  User selectedUser;
  bool initialized = false;

  void _onWidgetDidBuild(Function callback) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      callback();
    });
  }

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

    if (widget.defaultUser != null) {
      setState(() {
        selectedUser = widget.defaultUser;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final UserDataBloc _userDataBloc = BlocProvider.of<UserDataBloc>(context);

    return Scaffold(
        body: BlocBuilder(
            bloc: _userDataBloc,
            builder: (BuildContext context, UserDataState state) {
              final GlobalKey<RefreshIndicatorState> _refreshKey =
                  GlobalKey<RefreshIndicatorState>();

              _onWidgetDidBuild(() {
                print("batata");
                print(_refreshKey.currentState); // here
                _refreshKey.currentState?.show();
              });

              return LiquidPullToRefresh(
                key: _refreshKey,
                springAnimationDurationInMilliseconds: 500,
                showChildOpacityTransition: false,
                color: Theme.of(context).scaffoldBackgroundColor,
                backgroundColor: Theme.of(context).primaryColor,
                onRefresh: () {
                  _userDataBloc.dispatch(GetUsers());

                  if (state is UserDataLoading) {
                    return state.future;
                  }

                  return Future.delayed(Duration.zero);
                },
                child: CustomScrollView(
                  slivers: <Widget>[
                    SliverAppBar(
                      floating: false,
                      snap: false,
                      elevation: 0,
                      centerTitle: false,
                      backgroundColor: Colors.transparent,
                      title: Text(
                        'Selecionar cliente',
                        style: Theme.of(context).textTheme.title,
                      ),
                      leading: IconButton(
                        tooltip: "Voltar",
                        icon: Icon(
                          Icons.close,
                          color: Theme.of(context).textTheme.title.color,
                        ),
                        onPressed: () {
                          Navigator.pop(context, null);
                        },
                      ),
                      actions: <Widget>[
                        Container(
                          padding: EdgeInsets.only(right: 5),
                          child: Row(children: <Widget>[
                            FlatButton(
                              textColor: Theme.of(context).primaryColor,
                              shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(4)),
                              child: Text("Concluído"),
                              onPressed: () {
                                Navigator.pop(context, selectedUser);
                              },
                            ),
                          ]),
                        )
                      ],
                    ),
                    SliverList(
                      delegate: SliverChildListDelegate(<Widget>[
                        Builder(
                          builder: (BuildContext context) {
                            if (state is UserDataLoaded) {
                              AutoCompleteTextField<User> _autoCompleteField =
                                  AutoCompleteTextField<User>(
                                context: context,
                                itemSubmitted: (v) {},
                                decoration: InputDecoration(
                                    contentPadding: EdgeInsets.all(20),
                                    border: InputBorder.none,
                                    hintText: "Nome do cliente"),
                                key: _autoCompleteKey,
                                suggestions: state.user,
                                clearOnSubmit: false,
                                submitOnSuggestionTap: true,
                                itemFilter: (item, query) {
                                  return item.name
                                          .toLowerCase()
                                          .startsWith(query.toLowerCase()) &&
                                      !item.admin;
                                },
                                itemSorter: (a, b) {
                                  return a.name
                                      .toLowerCase()
                                      .compareTo(b.name.toLowerCase());
                                },
                                itemBuilder: (BuildContext context, User user) {
                                  return ListTile(
                                    selected: user.id == selectedUser?.id,
                                    leading: CircleAvatar(),
                                    title: Text(user.name),
                                    subtitle: Text(user.email),
                                  );
                                },
                              );

                              _autoCompleteField.itemSubmitted = (item) {
                                setState(() {
                                  _autoCompleteField.textField.controller.text =
                                      item.name;
                                  selectedUser = item;
                                });
                              };

                              _onWidgetDidBuild(() {
                                FocusScope.of(context).requestFocus(
                                    _autoCompleteField.textField.focusNode);
                              });

                              if (widget.defaultUser != null && !initialized) {
                                _onWidgetDidBuild(() {
                                  setState(() {
                                    _autoCompleteField.textField.controller
                                        .text = widget.defaultUser.name;
                                    initialized = !initialized;
                                  });
                                });
                              }

                              return _autoCompleteField;
                            }

                            return Container();
                          },
                        )
                      ]),
                    )
                  ],
                ),
              );
            }));
  }
}

Hey, I think I see your bug. You defined _refreshKey inside of your builder. So, instead of being in the state's scope, you're recreating it each time. Try moving it next your _autoCompleteKey if you haven't already figured this out days ago.

Thanks @Taormina, I'll try

@Taormina there's documentation in the code stating...

/// Creating the [LiquidPullToRefresh] with a [GlobalKey<LiquidPullToRefreshState>]
/// makes it possible to refer to the [LiquidPullToRefreshState].

However LiquidPullToRefreshState is private. Using RefreshIndicatorState throws "The method 'show' was called on null." The workaround I have is to not specify a class like so...

final GlobalKey _refreshIndicatorKey = GlobalKey();
// ...
(_refreshIndicatorKey.currentState as dynamic).show();

@zgosalvez Do you have a larger code snippet you can share from when you were using the RefreshIndicatorState?