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
?