使用 GlobalKey 从父小部件调用子小部件中的方法
Calling method in child widget from parent widget using GlobalKey
我正在使用全局键从父窗口小部件调用方法。我发现了这里选项 2 中提到的这种方法。
https://medium.com/flutter-community/flutter-communication-between-widgets-f5590230df1e
以下不是确切的代码,而是正在使用的代码片段。 chid 中的搜索方法即使从父级调用时也不会被调用。
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController _tabController;
bool showFab = true;
SearchState searchState = SearchState.SHOW_MENU;
TextEditingController _searchQuery;
bool _isSearching = false;
String searchQuery = "Search query";
GlobalKey<CustomersScreenState> _customerScreenState1 = GlobalKey();
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
});
print("search query " + newQuery); //This is getting printed
_customerScreenState1.currentState.search(newQuery); //Nothing happening here. not getting called
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.7,
leading: _isSearching ? const BackButton() : null,
title: _isSearching ? _buildSearchField() : _buildTitle(context),
actions: _buildActions(),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
tabs: <Widget>[
Tab(icon: Icon(Icons.camera_alt)),
Tab(text: "CHATS"),
Tab(
text: "STATUS",
),
Tab(
text: "CALLS",
),
],
)),
body: TabBarView(
controller: _tabController,
children: <Widget>[
CustomersScreen(key: _customerScreenState1)
],
),
}
class CustomersScreen extends StatefulWidget {
const CustomersScreen({Key key}) : super(key: key);
@override
CustomersScreenState createState() => CustomersScreenState();
}
class CustomersScreenState extends State<CustomersScreen> {
Firestore fireStore;
List<Customer> customers = [];
bool isLoading = false; // track if products fetching
bool hasMore = true; // flag for more products available or not
int documentLimit = 10; // documents to be fetched per request
DocumentSnapshot
lastDocument; // flag for last document from where next 10 records to be fetched
ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
fireStore = Firestore.instance;
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getCustomers();
}
});
getCustomers();
}
void search(Sting query){
//This method is not getting called.
}
}
编辑 1:
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
print("search query " + newQuery);
_customerScreenState1.currentState.search(newQuery); //moved inside setState still not working
});
}
我已将我的答案更改为您想要执行的工作示例。我看到这与您的代码之间的唯一区别是您的 chid 小部件没有构建功能,我想知道这是否会干扰您的状态。
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
GlobalKey<_ChildWidgetState> _childKey = GlobalKey<_ChildWidgetState>();
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ChildWidget(key: _childKey),
RaisedButton(
onPressed: () => callChildFunction(),
child: Text('Print'),
)
],
),
),
);
}
void callChildFunction(){
_childKey.currentState.changeChildText();
}
}
class ChildWidget extends StatefulWidget {
ChildWidget({Key key}): super(key: key);
@override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
String text = 'Child widget';
@override
Widget build(BuildContext context) {
return Container(
child: Text(text),
);
}
void changeChildText(){
setState(() {
text = 'called function';
});
}
}
仅凭片段很难说。我认为 search
方法是使用您的方法触发的,但您可能没有看到 UI 中的任何差异,因为在 search
方法运行后您没有触发构建方法。
只需尝试在 _HomeState
class.
中的 setState
回调中调用 _customerScreenState1.currentState.search(newQuery);
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
_customerScreenState1.currentState.search(newQuery);
});
print("search query " + newQuery); //This is getting printed
}
我正在使用全局键从父窗口小部件调用方法。我发现了这里选项 2 中提到的这种方法。 https://medium.com/flutter-community/flutter-communication-between-widgets-f5590230df1e
以下不是确切的代码,而是正在使用的代码片段。 chid 中的搜索方法即使从父级调用时也不会被调用。
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController _tabController;
bool showFab = true;
SearchState searchState = SearchState.SHOW_MENU;
TextEditingController _searchQuery;
bool _isSearching = false;
String searchQuery = "Search query";
GlobalKey<CustomersScreenState> _customerScreenState1 = GlobalKey();
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
});
print("search query " + newQuery); //This is getting printed
_customerScreenState1.currentState.search(newQuery); //Nothing happening here. not getting called
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.7,
leading: _isSearching ? const BackButton() : null,
title: _isSearching ? _buildSearchField() : _buildTitle(context),
actions: _buildActions(),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
tabs: <Widget>[
Tab(icon: Icon(Icons.camera_alt)),
Tab(text: "CHATS"),
Tab(
text: "STATUS",
),
Tab(
text: "CALLS",
),
],
)),
body: TabBarView(
controller: _tabController,
children: <Widget>[
CustomersScreen(key: _customerScreenState1)
],
),
}
class CustomersScreen extends StatefulWidget {
const CustomersScreen({Key key}) : super(key: key);
@override
CustomersScreenState createState() => CustomersScreenState();
}
class CustomersScreenState extends State<CustomersScreen> {
Firestore fireStore;
List<Customer> customers = [];
bool isLoading = false; // track if products fetching
bool hasMore = true; // flag for more products available or not
int documentLimit = 10; // documents to be fetched per request
DocumentSnapshot
lastDocument; // flag for last document from where next 10 records to be fetched
ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
fireStore = Firestore.instance;
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getCustomers();
}
});
getCustomers();
}
void search(Sting query){
//This method is not getting called.
}
}
编辑 1:
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
print("search query " + newQuery);
_customerScreenState1.currentState.search(newQuery); //moved inside setState still not working
});
}
我已将我的答案更改为您想要执行的工作示例。我看到这与您的代码之间的唯一区别是您的 chid 小部件没有构建功能,我想知道这是否会干扰您的状态。
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
GlobalKey<_ChildWidgetState> _childKey = GlobalKey<_ChildWidgetState>();
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ChildWidget(key: _childKey),
RaisedButton(
onPressed: () => callChildFunction(),
child: Text('Print'),
)
],
),
),
);
}
void callChildFunction(){
_childKey.currentState.changeChildText();
}
}
class ChildWidget extends StatefulWidget {
ChildWidget({Key key}): super(key: key);
@override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
String text = 'Child widget';
@override
Widget build(BuildContext context) {
return Container(
child: Text(text),
);
}
void changeChildText(){
setState(() {
text = 'called function';
});
}
}
仅凭片段很难说。我认为 search
方法是使用您的方法触发的,但您可能没有看到 UI 中的任何差异,因为在 search
方法运行后您没有触发构建方法。
只需尝试在 _HomeState
class.
setState
回调中调用 _customerScreenState1.currentState.search(newQuery);
void updateSearchQuery(String newQuery) {
setState(() {
searchQuery = newQuery;
_customerScreenState1.currentState.search(newQuery);
});
print("search query " + newQuery); //This is getting printed
}