0

I am trying to clean up my code and want to place one of my methods from a stateful widget inside of a different class that is also a stateful widget but whenever I try to call the method it does not recognize it unless the class that I am calling it from it a stateless widget. I was wondering what the best way to get around this would be without changing the class?

Here is a simple example of my problem, I am trying to call exampleStatefulWidget.testWidget() inside of MyHomePage which is a stateful widget.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
ExampleStatefulWidget exampleStatefulWidget = ExampleStatefulWidget();
ExampleStatelessWidget exampleStatelessWidget = ExampleStatelessWidget();

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
        exampleStatefulWidget.testWidget(), // Can not call method that is inside of a stateful widget
        exampleStatelessWidget.testWidget(); // Will call method but only if inside of a stateless widget
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class ExampleStatefulWidget extends StatefulWidget {
  const ExampleStatefulWidget({Key? key}) : super(key: key);

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

class _ExampleStatefulWidgetState extends State<ExampleStatefulWidget> {
  MyHomePage myHomePage = MyHomePage();

  Widget testWidget() {
    return Container(); // Do Something
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

class ExampleStatelessWidget extends StatelessWidget {
  const ExampleStatelessWidget({ Key? key }) : super(key: key);

  Widget testWidget() {
    return Container(); // Do Something
  }
  
  @override
  Widget build(BuildContext context) {
    return Container(
      
    );
  }
}
Cameron Johnson
  • 143
  • 1
  • 10
  • what are trying do inside `testWidget()`? – Md. Yeasin Sheikh Nov 12 '21 at 09:05
  • right now I am just trying to return a widget that contains a row and some buttons that uses setState hence the reason I need it to be a stateful widget – Cameron Johnson Nov 12 '21 at 09:19
  • I don't think you will be able to return a Widget from OnPressed function. Maybe that's the issue. – quim Nov 12 '21 at 09:24
  • `ExampleStatefulWidget` and `_ExampleStatefulWidgetState` are different class , you can create instacce of `_ExampleStatefulWidgetState` instead. and use the method. – Md. Yeasin Sheikh Nov 12 '21 at 09:25
  • Does this answer your question? [call method in one stateful widget from another stateful widget - Flutter](https://stackoverflow.com/questions/51029655/call-method-in-one-stateful-widget-from-another-stateful-widget-flutter) – ישו אוהב אותך Nov 12 '21 at 10:04

2 Answers2

0

ExampleStatefulWidget and _ExampleStatefulWidgetState are different class, you can create instance of _ExampleStatefulWidgetState instead. And use the method.

_ExampleStatefulWidgetState exampleStatefulWidget =
    _ExampleStatefulWidgetState();

In this case, uses will be like

_MyHomePageState

class _MyHomePageState extends State<MyHomePage> {
  Widget? widgetFromMethod;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (widgetFromMethod != null) widgetFromMethod!,
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          exampleStatelessWidget
              .testWidget(); // Will call method but only if inside of a stateless widget
          final gotWidget = exampleStatefulWidget.testWidget();

          setState(() {
            widgetFromMethod = gotWidget;
          });
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

_ExampleStatefulWidgetState

class _ExampleStatefulWidgetState extends State<ExampleStatefulWidget> {
  MyHomePage myHomePage = MyHomePage();

  Widget testWidget() {
    return Container(
      color: Colors.purple,
      width: 100,
      height: 100,
      child: Text("generated method from statefull"),
    ); // Do Something
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

if _ExampleStatefulWidgetState are on separate file, make it public removing _. it will be ExampleStatefulWidgetState

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
0

Calling a printLog method of SecondWidget (Child) from FirstWidget(Parent)

Note: This is not recommended. Use any state management lib to achive this (flutter_bloc, provider etc)

import 'package:flutter/material.dart';

class FirstWidget extends StatefulWidget {
  @override
  _FirstWidgetState createState() => _FirstWidgetState();
}

class _FirstWidgetState extends State<FirstWidget> {
  final key = GlobalKey<_SecondWidgetState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          alignment: Alignment.center,
          child: Column(
            children: [
              ElevatedButton(
                onPressed: () {
                  key.currentState?.printLog();
                },
                child: Text("Click"),
              ),
              SecondWidget(key)
            ],
          ),
        ),
      ),
    );
  }
}

class SecondWidget extends StatefulWidget {
  SecondWidget(Key key) : super(key: key);

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

class _SecondWidgetState extends State<SecondWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(padding: EdgeInsets.all(20), child: Container());
  }

  void printLog() {
    print("I am called");
  }
}
Sanjay Kumar
  • 1,135
  • 14
  • 27