从父类调用子类函数的Flutter

wdebmtf2  于 2023-01-18  发布在  Flutter
关注(0)|答案(6)|浏览(179)

代码

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
              // how can I call methodA from here?
            },
          ),
        ),
        body: HomePage(),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  void methodA() {}
}

问题:我想从IconButtononPressed()调用methodA()。我该怎么做呢?我知道如何从子类调用父类的方法,但这个用例是不同的。

pokxtpni

pokxtpni1#

我认为在这种情况下最好的做法是使用Flutter的程序员自己使用的方式!
波纹管代码是Flutter source中的一个示例。正如您在MyCustomForm小部件中所看到的,如果您想要访问TextField小部件 (在本示例中是MyCustomForm小部件的子项) 的text属性,则需要按如下方式使用其控制器...

class _MyCustomFormState extends State<MyCustomForm> {
  ...
  final myController = TextEditingController();
  ...
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...
      body: TextField(
        controller: myController,
      ),// TextField
      ...
      floatingActionButton: FloatingActionButton(
        ...
        onPressed: () {
          print(myController.text);
        },
        ...
      ),// FloatingActionButton
    );
  }
}

现在受此启发,同时也知道Flutter通过引用传递其对象参数,因此我们需要为子类提供一个控制器类,以便能够通过控制器对象访问子类的字段和函数 (如上例中的TextField小部件)......在您的情况下,我们可以这样做:

class HomePageController {
  void Function() methodA;
}

class MyApp extends StatelessWidget {

  final HomePageController myController = HomePageController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
              myController.methodA();
            },
          ),// IconButton
        ),// AppBar
        body: HomePage(
          controller: myController,
        ),// HomePage
      ),
    );
  }
}

class HomePage extends StatefulWidget {

  final HomePageController controller;

  HomePage({ this.controller });

  @override
  _HomePageState createState() => _HomePageState(controller);
}

class _HomePageState extends State<HomePage> {

  _HomePageState(HomePageController _controller) {
    _controller.methodA = methodA;
  }

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

  void methodA() {}
}

如本代码所示,myController的引用通过HomePage到达**_HomePageState的构造函数,然后获取methodA函数的引用......现在,methodA可在MyApp类中通过myController**访问!
希望对你有帮助!:))

ryevplcw

ryevplcw2#

感谢Günter Zöchbauer为我指明了正确的方向。我正在使用GlobalKey来完成事情。但是,请将GlobalKeycare一起使用

GlobalKey<_HomePageState> globalKey = GlobalKey();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
             globalKey.currentState.methodA();
            },
          ),
        ),
        body: HomePage(key: globalKey),
      ),
    );
  }
}
class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  void methodA() {}
}
7qhs6swi

7qhs6swi3#

2021年

我相信这是使用typedef和类似构建器的小部件的最健壮的解决方案。

import 'package:flutter/material.dart';

typedef MyBuilder = void Function(BuildContext context, void Function() methodA);

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

class MyApp extends StatelessWidget {
  late void Function() myMethod;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
              // how can I call methodA from here?
              myMethod.call();
            },
          ),
        ),
        body: HomePage(builder: (BuildContext context, void Function() methodA) {
          myMethod = methodA;
        },),
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  final MyBuilder builder;

  const HomePage({Key? key, required this.builder}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    widget.builder.call(context, methodA);
    return Text('HomePage');
  }

  void methodA() {
    print('test');
  }
}
ntjbwcob

ntjbwcob4#

上面的答案对我不起作用,相反,我只是替换了全局键,它工作得很好:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
 return MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      leading: IconButton(
        icon: Icon(Icons.help),
        onPressed: () {
         //call it like this:
         HomePage.globalKey.currentState.methodA();
        },
      ),
    ),
    body: HomePage(),
  ),
);
 }
}

class HomePage extends StatefulWidget {
//Add this key like this:
static final GlobalKey<_HomePageState> globalKey = GlobalKey();
super(key: globalKey);

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

class _HomePageState extends State<HomePage> {
 @override
  Widget build(BuildContext context) {
  return Container();
 }

 void methodA() {}
}

希望一切正常:)

mf98qq94

mf98qq945#

实际上,您无法执行此操作,因为_HomePageState是私有的。请删除HomePageState前面的_符号,这样它将是公共的,并且您可以使用HomePageState().methodA();调用methodA(

pbossiut

pbossiut6#

调用父函数可以通过callback来完成,但是我认为从父控件调用子函数是没有必要的。如果你的父控件是StateFull,你只需要setState(() {});来刷新子控件,为什么要调用子函数呢?

相关问题