使用 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
}