web-dev-qa-db-fra.com

onResume () et onPause () pour les widgets sur Flutter

À l'heure actuelle, un widget n'a que initeState () qui est déclenché la toute première fois qu'un widget est créé, et dispose (), qui est déclenché lorsque le widget est détruit. Existe-t-il une méthode pour détecter le moment où un widget revient au premier plan? et quand un widget est sur le point d’aller en arrière-plan parce qu’un autre widget vient d’être mis au premier plan? C'est l'équivalent de onResume et onPause déclenchés pour Android, et viewWillAppear et viewWillDisappear pour ios

14
user3217522

Le cas le plus courant où vous souhaitez le faire est si vous avez une animation en cours d'exécution et que vous ne voulez pas consommer de ressources en arrière-plan. Dans ce cas, vous devez étendre votre State avec TickerProviderStateMixin et utiliser votre State comme argument vsync pour le AnimationController. Flutter prendra soin d'appeler uniquement les écouteurs du contrôleur d'animation lorsque votre State est visible.

Si vous souhaitez que les State qui vivent dans votre PageRoute soient supprimés lorsque le PageRoute est masqué par un autre contenu, vous pouvez passer un maintainState argument de false à votre constructeur PageRoute. Si vous faites cela, votre State se réinitialisera (et ses enfants) quand il sera caché et devra se reconstruire dans initState en utilisant les propriétés passées en arguments constructeur à son widget. Vous pouvez utiliser un modèle ou une classe de contrôleur, ou PageStorage , pour conserver les informations de progression de l'utilisateur si vous ne souhaitez pas une réinitialisation complète.

Voici un exemple d'application qui illustre ces concepts.

screen 1screen 2screen 3

import 'package:flutter/material.Dart';

void main() {
  runApp(new MaterialApp(
    onGenerateRoute: (RouteSettings settings) {
      if (settings.name == '/') {
        return new MaterialPageRoute<Null>(
          settings: settings,
          builder: (_) => new MyApp(),
          maintainState: false,
        );
      }
      return null;
    }
  ));
}

class MyApp extends StatefulWidget {
  MyAppState createState() => new MyAppState();
}

class MyAppState extends State<MyApp> with TickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    print("initState was called");
    _controller = new AnimationController(vsync: this)
      ..repeat(min: 0.0, max: 1.0, period: const Duration(seconds: 1))
      ..addListener(() {
        print('animation value ${_controller.value}');
      });
    super.initState();
  }

  @override
  void dispose() {
    print("dispose was called");
    _controller.dispose();
    super.dispose();
  }

  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('home screen')
      ),
      body: new Center(
        child: new RaisedButton(
          onPressed: () {
            setState(() {
              _counter++;
            });
          },
          child: new Text('Button pressed $_counter times'),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.remove_red_eye),
        onPressed: () {
          Navigator.Push(context, new MaterialPageRoute(
            builder: (BuildContext context) {
              return new MySecondPage(counter: _counter);
            },
          ));
        },
      ),
    );
  }
}

class MySecondPage extends StatelessWidget {
  MySecondPage({ this.counter });

  final int counter;

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Certificate of achievement'),
      ),
      body: new Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          new Icon(Icons.developer_mode, size: 200.0),
          new Text(
            'Congrats, you clicked $counter times.',
            style: Theme.of(context).textTheme.title,
            textAlign: TextAlign.center,
          ),
          new Text(
            'All your progress has now been lost.',
            style: Theme.of(context).textTheme.subhead,
            textAlign: TextAlign.center,
          ),
        ],
      ),
    );
  }
}
9
Collin Jackson

Il existe un appelant de classe abstraite WidgetsBindingObserver

https://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html

dans

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    setState(() {
            _notification = state;
    });
  }

il y a "l'état", peut être géré comme

switch(state) {
  case AppLifecycleState.resumed:
    // Handle this case
    break;
  case AppLifecycleState.inactive:
    // Handle this case
    break;
  case AppLifecycleState.paused:
    // Handle this case
    break;
  case AppLifecycleState.suspending:
    // Handle this case
    break;
}
31
Mamnarock