Trigger a tab function from another widget

Asked

Viewed 45 times

-1

Communication between screens is essential in an application.

In this case I am trying to conduct a search from a Searchdelegate

But when I return from the Searchdelegate I cannot communicate with the internal tab

For example:

Home.Dart

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
  TabController _tabController;
  List<String> _itensMenu = ["Sair"]; 
  _escolherMenuItem(String itemEscolhido) {
    switch (itemEscolhido) {
      case "Sair":
        _sairDoApp();
    }
  }

  Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
             actions: <Widget>[
          IconButton(
              icon: Icon(Icons.search),
              onPressed: () async {
                String res = await showSearch(
                    context: context, delegate: CustomSearchDelegate());
                AbaProdutos().pesquisar(res);
              }),
          PopupMenuButton(
              onSelected: _escolherMenuItem,
              itemBuilder: (context) {
                return _itensMenu.map((String item) {
                  return PopupMenuItem<String>(value: item, child: Text(item));
                }).toList();
              })
        ],
        )
      )
  }
}

Notice that I am calling the following function: AbaProdutos().pesquisar(res)

Abaprodutos.Dart

class AbaProdutos extends StatefulWidget {
  pesquisar(param) => createState().pesquisar(param);

  @override
  _AbaProdutosState createState() => _AbaProdutosState();
}

class _AbaProdutosState extends State<AbaProdutos> {
    
  pesquisar(param) {
    print("pesquisar param " + param);
    if (this.mounted) {
      print("montado ");
      setState(() {
        _strPesquisar = param;
        _paginaAtual = 1;
        _obterProdutos();
      });
    } else {
      print("não montado");
    }
  }

}

I can even get to this function. I’m doing the test if it’s mounted.

But it never gets inside the if( this.mounted )

And when I take the if( this.mounted ) he makes the following mistake

E/flutter (32036): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: setState() called in constructor: _Abaprodutosstate#06c34(Lifecycle state: created, no widget, not Mounted) E/flutter (32036): This Happens when you call setState() on a State Object for a widget that hasn’t been inserted into the widget Tree yet. It is not necessary to call setState() in the constructor, Since the state is already assumed to be Dirty when it is initially created.

The question:

How to make the Home search function work within the tab without problems?

Or even if there’s a way I keep hearing changes to the home variable inside the tab

1 answer

0

  • Explaining the problem:

You’re doing a check if (this.mounted). As the name says, this property specifies whether the widget in question is inserted in the Widgets tree or not.

Documentation can be read here (in English).

Whether this State Object is Currently in a Tree.

After Creating a State Object and before Calling initState,[...]

That is, only after the creation of the state object and insertion of that widget in the tree will that variable be considered as true.

The way you presented it, this widget is not inserted anywhere. You simply create a new instance of it with AbaProdutos(). This newly created instance within the onPressed is not being displayed. That’s why if you check if it is displayed, the answer will be "no" and you will not enter the if.

You probably have another instance of this "tab" somewhere else. By your question I couldn’t see where. And you want to call the method pesquisar of that particular instance.

Another problem made by you has the same principle. When you do:

pesquisar(param) => createState().pesquisar(param);

You are calling the search function a new state variable, which is not the one associated with the widget. createState() calls the builder of this class. I don’t believe this should work.

  • Strategies for solution:
    • Use a dependency injection and state management solution:

The correct for this case it is better to manage your state. As you said in the question, communication between screens is paramount in an app, and for that you need a robust and concrete solution to do so. Gambiarras like the one mentioned below (or others not mentioned) only increases the possibility of error, the inefficiency of the application, and prevents the scalability of the project. The way it’s shown in the question, you apparently don’t use any kind of state management.

The types of state management solutions are many, and a good compiled of them can be found on the official Flutter website, here. This is material for many and many questions and it would be impossible to answer succinctly here. On this very site the first link is a introducing for status management. Recommended by Google is the Provider and I believe he is the simplest and straightest to understand.

I suggest studying this part and analyzing the best case for your specific application.

I also leave here a solution not recommended, and more gambiarra for didactic reasons.

  • Save the tab instance to a variable (Not recommended):

The first thing that comes to mind when understanding this problem is to save a reference to that tab, and call the function using that reference. I’ve seen people who invent a lot of static methods and just call them (as if their entire project were done by Singletons). This will work, but you lose many advantages over how Flutter will manage your Widgets tree and its respective state objects. But at first it would solve your problem and maybe in a small application the consequences would not be so visible.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.