Search code examples
user-interfacefluttertriggerstimeoutflutter-layout

How to call a method after a no-activity timeout in Flutter?


What would be the best way to implement the following functionality:

After waiting a specified amount of time (defined by a constant variable) since the user's last interaction w/ the app, automatically call a function to add a couple of widgets to the page.


Solution

  • I haven't really tried this, but with the experience I got working with flutter,

    I'd say you could create a gesture detector at the top of your widget tree that will capture whenever the user taps the screen.

    You could for example record an int with the timestamp and update this value inside an inherited widget (will probably have to be on top of the gesture detector)

    finally, wherever widget needs to listen to this could have a timer that checks the time every x amount of time and compares if the touch was made 1 to 10 seconds before.

    The inherited widget could be like so:

    class MyInherited extends StatefulWidget {
      static MyInheritedData of(BuildContext context) =>
          context.inheritFromWidgetOfExactType(MyInheritedData) as MyInheritedData;
    
      const MyInherited({Key key, this.child}) : super(key: key);
    
      final Widget child;
    
      @override
      _MyInheritedState createState() => _MyInheritedState();
    }
    class _MyInheritedState extends State<MyInherited> {
      String myField;
    
      void onMyFieldChange(String newValue) {
          myField = newValue;
      }
    
      @override
      Widget build(BuildContext context) {
        return MyInheritedData(
          myField: myField,
          onMyFieldChange: onMyFieldChange,
          child: widget.child,
        );
      }
    }
    
    class MyInheritedData extends InheritedWidget {
      final String myField;
      final ValueChanged<String> onMyFieldChange;
    
      MyInheritedData({
        Key key,
        this.myField,
        this.onMyFieldChange,
        Widget child,
      }) : super(key: key, child: child);
    
      @override
      bool updateShouldNotify(MyInheritedData oldWidget) {
        return oldWidget.myField != myField ||
            oldWidget.onMyFieldChange != onMyFieldChange;
      }
    }
    

    The top of your widget tree would look something like this:

    GestureDetector(
      onTap: (){
        // Update the value of your field
      }
    

    Lastly, whenever you need to listen for this change you could add a timer like this:

      Timer timer;
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) {
          timer = Timer.periodic(Duration(seconds: 10), (Timer t) {
            // Get your inherited widget here and check the value, compare it and act as you pleased
          });
        });
      }
    
      @override
      void dispose() {
        timer?.cancel();
        super.dispose();
      }
    

    I know this might not be a perfect example but hopefully aims you to the right path! I didn't have time to make a more robust answer but wanted to give my point of view.

    Credits to the author of the correct answer in this question as I took the inherited widget example from his response Flutter: How to correctly use an Inherited Widget?