Flutter -始终在页面出现时执行函数

42fyovps  于 2022-12-14  发布在  Flutter
关注(0)|答案(5)|浏览(303)

如何使name()函数在Page1页面出现时运行?
在下面的代码中,在转到Page2之前,我执行dispose() Already inside Page2。如果我单击后退按钮或Android的物理按钮,则不会执行name()函数,但如果我单击'go to Page1'按钮,则会执行name()函数。
你能帮我在Page1出现时总是执行name()函数吗?

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {  
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
      routes: <String, WidgetBuilder> {
        '/page2': (BuildContext context) => new Page2(),
      },
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String nameScreen;

  String name() {
    return 'foo1';
  }

  @override
  void initState() {
    super.initState();
    this.nameScreen = name();

  }

  @override
  void dispose() {
    this.nameScreen = '';
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Page 1'),
        backgroundColor: new Color(0xFF26C6DA),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new RaisedButton(
              child: const Text('go to Page2'),
              onPressed: () async {
                dispose();
                bool isLoggedIn = await Navigator.of(context).pushNamed('/page2');
                if (isLoggedIn) {
                  setState((){
                    this.nameScreen = name();
                  });
                }
              },
            ),            
            new Text(
              '$nameScreen',              
            ),
          ],
        ),
      ),
    );
  }
}

class Page2 extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return new Scaffold( 
      appBar: new AppBar(
        title: new Text('Page 2'),
        backgroundColor: new Color(0xFFE57373)
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new RaisedButton(
              child: const Text('go back to Page1'),
              onPressed: () {
                Navigator.pop(context, true);
              }
            ),
          ],
        ),
      ),
    );
  }
}
9vw9lbht

9vw9lbht1#

当您希望使用pop并在以后更改State时,根本不需要调用dispose,因为dispose将从树中删除当前对象,这不会转换为您试图开发的逻辑。
你确实可以重写BackButton,并将相同的Navigator.pop(context, result)调用传递给它。检查下面的例子,我稍微调整了一下你的代码,向你展示了nameScreen字段中每个State之间的区别。我希望这对你有帮助。

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String nameScreen = "";

  String name() {
    return 'foo1';
  }

  @override
  void initState() {
    super.initState();
    this.nameScreen = "From initState";

  }

@override
void dipose(){
    super.dispose();
}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page 1'),
        backgroundColor: Color(0xFF26C6DA),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: const Text('go to Page2'),
              onPressed: () async {
                //dispose(); ///No need for dispose
                String result = await Navigator.of(context).pushNamed('/page2');

                  setState((){
                    this.nameScreen = result;
                  });

              },
            ),
            Text(
              '$nameScreen',
            ),
          ],
        ),
      ),
    );
  }
}

class Page2 extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: ()async{
            Navigator.pop(context,"From BackButton");
          }),
          title: const Text('Page 2'),
          backgroundColor: Color(0xFFE57373)
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
                child: const Text('go back to Page1'),
                onPressed: () {
                  Navigator.pop(context, "From RaisedButton");
                }
            ),
          ],
        ),
      ),
    );
  }
7fyelxc5

7fyelxc52#

执行此操作的一种方法是在Navigator小部件上使用.whenComplete()方法。
假设你要从第一页转到第二页,这里你必须传递functionThatSetsTheState作为代码导航部分的指针。
该函数如下所示,应该位于有状态小部件中。

void functionThatSetsTheState(){
    setState(() {});
}

您的导航代码为OnPressedOnTapOnLongPress等。

Navigator.of(context)
    .push(
        MaterialPageRoute(builder: (BuildContext context) => SecondPage()))
    .whenComplete(() => {functionThatSetsTheState()});
ycl3bljg

ycl3bljg3#

如果你想在页面出现时执行某个函数,你可以使用RouteObserves,你必须在你想运行的页面上实现RouteAware,在屏幕出现时执行函数,你必须在你的Page1上这样做

final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>(); // add this on your main class
void main() {
  runApp(MaterialApp(
    home: Container(),
    navigatorObservers: [routeObserver], // add observer here;
  ));
} 



// your page where func should run whenever this page appears
class MyHomePage extends StatefulWidget with RouteAware {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String nameScreen = "";

  String name() {
    return 'foo1';
  }

  @override
  void initState() {
    super.initState();
    this.nameScreen = "From initState";

  }

 @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

// implementing RouteAware method
void didPush() {
// Route was pushed onto navigator and is now topmost route.
    name(); // your func goes here
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page 1'),
        backgroundColor: Color(0xFF26C6DA),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: const Text('go to Page2'),
              onPressed: () async {
                //dispose(); ///No need for dispose
                String result = await Navigator.of(context).pushNamed('/page2');

                  setState((){
                    this.nameScreen = result;
                  });

              },
            ),
            Text(
              '$nameScreen',
            ),
          ],
        ),
      ),
    );
  }
}

您可以前往此链接获取更多说明https://api.flutter.dev/flutter/widgets/RouteObserver-class.html

oprakyz7

oprakyz74#

你可以覆盖第二个屏幕上的后退按钮。

WillPopScope(
    onWillPop: () {
       print('back pressed');
       Navigator.pop(context, "From BackButton");
       return true;
      },
    child: Scaffold(...)
t5fffqht

t5fffqht5#

假设您要从第1页导航到第2页,并在第2页加载后立即执行第2页中的函数(用于在第2页加载时立即显示对话框):
您可以通过在第2页的initStatedidChangeDependencies中添加以下内容来完成此操作:

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    // Function to execute
  });

如果你想在执行函数之前添加一些逻辑来放置一个条件,只需在页面1中推送一个参数:

Navigator.of(context).pushNamed("/page-2", arguments : true)

最后,第2页中的代码变为:

_functionToExecute(){
  print("done");
  }
 @override
 void didChangeDependencies() {
 
  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    if(ModalRoute.of(context).settings.arguments)
    _functionToExecute()
  });
 }

相关问题