112

Does flutter have a method like Activity.resume() which can tell developer the user has gone back to the activity.

When I pick the data from internet in Page-B and go back to Page-A, how can I let Page-A know that the data is prepared.

4

10 回答 10

226
  1. createState() 当Framework被指示构建StatefulWidget时,它立即调用createState()

  2. mounted为真:createState创建您的状态类时,将 abuildContext分配给该状态。buildContext是,过于简化,在部件树中放置这个部件的位置。这是一个更长的解释。所有小部件都有一个bool this.mounted属性。buildContext分配时变为真。setState卸载小部件时调用是错误的。

  3. initState() 这是创建小部件时调用的第一个方法(当然是在类构造函数之后。)initState调用一次且仅调用一次。它必须调用super.initState().

  4. didChangeDependencies()initState在第一次构建小部件 后立即调用此方法。

  5. build(): 这个方法经常被调用。它是必需的,它必须返回一个 Widget。

  6. didUpdateWidget(Widget oldWidget): 如果父部件发生变化并且必须重建这个部件(因为它需要给它不同的数据),但是它正在用相同的 重建runtimeType,那么这个方法被调用。这是因为 Flutter 正在重用状态,这是长期存在的。在这种情况下,您可能需要再次初始化一些数据,就像在initState.

  7. setState() 这个方法经常被框架本身和开发者调用。它用于通知框架数据已更改

  8. deactivate() 当从树中移除 State 时调用 Deactivate,但它可能会在当前帧更改完成之前重新插入。这种方法的存在基本上是因为 State 对象可以从树中的一个点移动到另一个点。

  9. dispose(): dispose()当状态对象被移除时调用,这是永久的。此方法是您应该取消订阅和取消所有动画、流等的地方。

  10. mounted为假:setState状态对象永远不能重新挂载,如果被调用 会抛出错误。

于 2018-11-19T17:25:27.013 回答
53

在此处输入图像描述 构造函数

这个函数不属于生命周期,因为此时widget属性的State为空,如果要在构造函数中访问widget属性是行不通的。但构造函数必须是第一次调用。

创建状态

当 Flutter 被指示构建一个StatefulWidget.createState()

初始状态

当此对象插入树中时调用。

在调用时插入渲染树时,该函数在生命周期中只调用一次。这里可以做一些初始化,比如初始化State变量。

设置状态

setState()方法经常被 Flutter 框架本身和开发者调用。

didChangeDependencies

当此 [State] 对象的依赖项发生更改时调用。

didUpdateWidget

每当小部件配置更改时调用。

停用

当从树中删除此对象时调用。在 dispose 之前,我们将调用这个函数。

处置

当此对象从树中永久删除时调用。

didChangeAppLifecycleState

当系统将应用程序置于后台或将应用程序返回到前台时调用。

这里有一个很好的详细文档:https ://www.bookstack.cn/read/flutterbyexample/aebe8dda4df3319f.md

    import 'package:flutter/material.dart';

    class ScreenLifecyle extends StatefulWidget {
    ScreenLifecyleState state;

    //createState(): When the Framework is instructed to build a StatefulWidget, it immediately calls createState()
    @override
    State<StatefulWidget> createState() {
        // TODO: implement createState
        return ScreenLifecyleState();
    }
    }

    class ScreenLifecyleState extends State<ScreenLifecyle> {
    /*
    mounted is true: When createState creates your state class, a buildContext is assigned to that state.
    BuildContext is, overly simplified, the place in the widget tree in which this widget is placed.
    Here's a longer explanation. All widgets have a bool this.mounted property.
    It is turned true when the buildContext is assigned. It is an error to call setState when a widget is unmounted.
    mounted is false: The state object can never remount, and an error is thrown is setState is called.
    */

    /*
    This is the first method called when the widget is created (after the class constructor, of course.)
    initState is called once and only once. It must called super.initState().
    */
    @override
    void initState() {
        // TODO: implement initState
        super.initState();
        print("initState");
    }

    /*
    This method is called immediately after initState on the first time the widget is built.
    */
    @override
    void didChangeDependencies() {
        // TODO: implement didChangeDependencies
        super.didChangeDependencies();
        print("didChangeDependencies");
    }

    /*
    build(): This method is called often. It is required, and it must return a Widget.
    */
    @override
    Widget build(BuildContext context) {
        print("build");

        // TODO: implement build
        return Container();
    }

    /*
    If the parent widget changes and has to rebuild this widget (because it needs to give it different data),
    but it's being rebuilt with the same runtimeType, then this method is called.
    This is because Flutter is re-using the state, which is long lived.
    In this case, you may want to initialize some data again, as you would in initState.
    */
    @override
    void didUpdateWidget(ScreenLifecyle oldWidget) {
        print("didUpdateWidget");

        // TODO: implement didUpdateWidget
        super.didUpdateWidget(oldWidget);
    }

    @override
    void setState(fn) {
        print("setState");

        // TODO: implement setState
        super.setState(fn);
    }

    /*
    Deactivate is called when State is removed from the tree,
    but it might be reinserted before the current frame change is finished.
    This method exists basically because State objects can be moved from one point in a tree to another.
    */
    @override
    void deactivate() {
        // TODO: implement deactivate
        print("deactivate");
        super.deactivate();
    }

    /*
    Dispose is called when the State object is removed, which is permanent.
    This method is where you should unsubscribe and cancel all animations, streams, etc.
    */
    @override
    void dispose() {
        // TODO: implement dispose
        super.dispose();
     }

       @override
        void didChangeAppLifecycleState(AppLifecycleState state) {
            super.didChangeAppLifecycleState(state);
            switch (state) {
            case AppLifecycleState.inactive:
                print('appLifeCycleState inactive');
                break;
            case AppLifecycleState.resumed:
                print('appLifeCycleState resumed');
                break;
            case AppLifecycleState.paused:
                print('appLifeCycleState paused');
                break;
            case AppLifecycleState.suspending:
                print('appLifeCycleState suspending');
                break;
            }
        }

  }
 
于 2019-08-29T05:03:50.263 回答
23

这里有一个例子:https ://github.com/flutter/flutter/blob/master/examples/layers/services/lifecycle.dart

你需要使用WidgetsBindingObserver

于 2017-01-05T08:03:16.810 回答
18

只有StatefulWidget持有 state 。它的生命周期如下

  • createState() :当我们构建一个新的 StatefulWidget 时,这个立即调用 createState() 并且这个覆盖方法必须存在
  • initState() :它是Widget创建后调用的第一个方法。这相当于我们的onCreate()和viewDidLoad()
  • didChangeDependencies() :在第一次构建小部件时,在 initState() 之后立即调用此方法
  • build() : 在 didChangeDependencies() 之后调用。所有的 GUI 都在这里渲染,并且每次需要渲染 UI 时都会被调用
  • didUpdateWidget() :一旦父 Widget 发生更改并需要重绘 UI,它将被调用
  • deactivate() :框架在从树中删除此 State 对象时调用此方法
  • dispose() :当此对象及其状态从树中永久删除并且永远不会再次构建时调用。

AppLifecycleState 如下

  • 非活动 - 应用程序处于非活动状态并且未接收用户输入。仅限 iOS

  • paused - 应用程序当前对用户不可见,不响应用户输入,并且在后台运行。

  • resumed - 应用程序可见并响应用户输入。

  • 暂停 - 应用程序将暂时暂停。仅限安卓

于 2019-12-10T07:01:21.297 回答
13

应用生命周期

对于 LifeCycle,您需要 WidgetsBindingObserver 在应用程序在前台和后台运行时使用它。

import 'package:flutter/widgets.dart';
  class YourWidgetState extends State<YourWidget> with WidgetsBindingObserver {

       @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }


      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }


       @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
        if (state == AppLifecycleState.resumed) {
           //do your stuff
        }
      }
    }

OnResume但就我而言,当我从一个屏幕移动到另一个屏幕时,我无法捕捉到这种情况。所以下面的代码与startActivityForResult.

当您进行其他活动时使用此代码

Navigator.push(context,
              MaterialPageRoute(builder: (context) => ProductDetails(pid: productList[index]["pid"],),
                  settings: RouteSettings(name: '/productdetail')),).then((value){
                    setState(() {
                      length=value;
                    });
                    debugPrint('CHECK BACK FROM DETAIL $length');
            });

当你按下回

onPressed: (){Navigator.pop(context,length);}
于 2019-03-19T05:57:31.137 回答
6

我认为 Flutter 应用程序生命周期回调在这里不会对您有所帮助。你可以试试这个逻辑。

在第一页(导航到第二页时)

Navigator.push(context, MaterialPageRoute(builder: (context) => Page2())).then((value) {
  print("Value returned form Page 2 = $value");
};

在第 2 页(导航回第 1 页时)

Navigator.pop(context, returnedValue);

生命周期回调

void main() => runApp(HomePage());

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

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print("Current state = $state");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Lifecycle")),
        body: Center(child: Text("Center"),),
      ),
    );
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}
于 2019-02-05T15:09:27.393 回答
3
  1. createState():当我们创建一个有状态的小部件时,Flutter 框架会指示 createState() 方法。

    @override _DeveloperLibsWidgetState createState() => _DeveloperLibsWidgetState();

2.mounted (true/false):一旦我们创建了一个State对象,框架在调用initState()方法之前通过关联一个BuildContext来挂载这个State对象。所有小部件都有一个 bool 安装属性。分配 buildContext 时变为真。

bool get mounted => _element != null;
  1. initState():这是在类构造函数之后创建有状态小部件时调用的第一个方法。initState() 只被调用一次。它必须调用 super.initState()。

    @override initState() { super.initState(); // 去做 }

  2. didChangeDependencies():在第一次构建小部件时,在 initState() 方法之后立即调用此方法。

    @protected @mustCallSuper void didChangeDependencies() {

    }

  3. build():它显示了由小部件表示的用户界面的一部分。框架在几种不同的情况下调用此方法: 在调用 initState() 方法之后。框架总是在调用 didUpdateWidget 后调用 build() 方法,在接收到 setState 的调用后更新屏幕。

    @override Widget build(BuildContext context, MyButtonState state) { return Container(color: const Color(0xFF2DBD3A));
    }

  4. didUpdateWidget(Widget oldWidget):如果父小部件更改配置并且必须重建此小部件。但它正在使用相同的 runtimeType 重建,然后调用 didUpdateWidget() 方法。

    @mustCallSuper @protected void didUpdateWidget(covariant T oldWidget) {

    }

  5. setState():从框架和开发人员调用此方法。我们可以更改 State 对象的内部状态,并在传递给 setState() 的函数中进行更改。

    @override _DeveloperLibsWidgetState createState() => _DeveloperLibsWidgetState();

  6. deactivate():当从小部件树中删除 State 时调用它,但它可能会在当前帧更改完成之前重新插入。

    @protected @mustCallSuper void deactivate() { }

  7. dispose():当状态对象被永久删除时调用。在这里您可以取消订阅和取消所有动画、流等。

    @protected @mustCallSuper void dispose() { assert(_debugLifecycleState == _StateLifecycle.ready); 断言(() { _debugLifecycleState = _StateLifecycle.defunct; 返回 true; }()); }

于 2020-07-17T03:49:18.610 回答
0

您可以在Flutter扩展类中模拟onResumeonPause声明。确保使用 push() 或 pushNamed() 方法推送新路由。LifecycleState

/// Inherit this State to be notified of lifecycle events, including popping and pushing routes.
///
/// Use `pushNamed()` or `push()` method to track lifecycle events when navigating to another route.
abstract class LifecycleState <T extends StatefulWidget> extends State<T>
    with WidgetsBindingObserver {
  ResumeResult resumeResult = new ResumeResult();
  bool _isPaused = false;

  AppLifecycleState lastAppState = AppLifecycleState.resumed;

  void onResume() {}

  void onPause() {}

  /// Use instead of Navigator.push(), it fires onResume() after route popped
Future<T> push<T extends Object>(BuildContext context, Route<T> route, [String source]) {
    _isPaused = true;
    onPause();

    return Navigator.of(context).push(route).then((value) {
        _isPaused = false;

        resumeResult.data = value;
        resumeResult.source = source;

        onResume();
        return value;
    });
}

/// Use instead of Navigator.pushNamed(), it fires onResume() after route popped
Future<T> pushNamed<T extends Object>(BuildContext context, String routeName, {Object arguments}) {
    _isPaused = true;
    onPause();

    return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments).then((value) {
        _isPaused = false;

        resumeResult.data = value;
        resumeResult.source = routeName;

        onResume();
        return value;
    });
}

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused) {
      if (!_isPaused) {
        onPause();
      }
    } else if (state == AppLifecycleState.resumed &&
        lastAppState == AppLifecycleState.paused) {
      if (!_isPaused) {
        onResume();
      }
    }
    lastAppState = state;
  }
}

class ResumeResult {
  dynamic data;
  String source;
}
于 2021-02-14T18:54:51.747 回答
0

因为这里的每个人都在谈论应用程序生命周期,而不是解决 OP 提出的问题。这是问题的答案。

要求是他想从页面A打开页面B,假设从页面B中选择文件,一旦选择文件,他想回到页面A并需要处理页面A中选择的文件。就像在android中我们可以在 onActivityResult() 方法中执行此操作。以下是我们可以在颤振中实现的方式。

您可以从页面 A 打开页面 B,如下所示

Map results =  await Navigator.of(context).push(MaterialPageRoute(
      builder: (BuildContext context) {
        return new PageB(title: "Choose File");
        },
      ));

    if (results != null && results.containsKey('selection')) {
      setState(() {
        _selection = results['selection'];
      });

    **//here you can do whatever you want to do with selection variable.**

    }

在页面 B 中,您可以选择文件或您需要返回页面 A 的任何内容,如下所示(选择后返回文件或任何其他变量。

Navigator.of(context).pop({'selection':file});
于 2020-09-30T09:50:07.417 回答
0

我知道我可能会迟到一点,但会回答这个问题以防其他人需要答案,请参阅此解决方案https://stackoverflow.com/a/58504433/3037840 但我想澄清一些事情,在你的状态实现RouteAwaremixin 后的小部件,请注意:

@override
  void didPushNext() { //similar to onPause
    // will be called when a new route has been pushed, and the current route is no longer visible. acts similar to onPause
  }

  @override
  void didPopNext() { //similar to onResume
     // will be called when the top route has been popped off, and the current route shows up. acts similar to onResume when you are navigated back to your activity/fragment
  }
于 2021-06-03T04:52:43.977 回答