OnResume() и onPause() для виджетов на Flutter

В настоящее время виджет имеет только initeState(), который запускается с первого раза, когда создается виджет, и dispose(), который запускается при уничтожении виджета. Есть ли способ обнаружить, когда виджет возвращается на передний план? и когда виджет вот-вот перейдет на задний план, потому что еще один виджет был наложен? Это эквивалент onResume и onPause запускается для Android, а viewWillAppear и viewWillDisappear для ios

Ответ 1

Наиболее распространенный случай, когда вы захотите сделать это, если у вас запущена анимация и вы не хотите использовать ресурсы в фоновом режиме. В этом случае вы должны расширить свой State с помощью TickerProviderStateMixin и использовать свой State в качестве аргумента vsync для AnimationController. Flutter позаботится о том, чтобы вызывать слушателей контроллера анимации только тогда, когда видимо ваше State.

Если вы хотите, чтобы State, которые живут в вашем PageRoute, чтобы быть утилизированы, когда PageRoute затемняется другим содержимым, вы можете передать maintainState аргумент false для вашего PageRoute конструктора. Если вы сделаете это, ваше State сбросит себя (и его дочерние initState), когда оно будет скрыто, и ему придется пересоздать себя в initState используя свойства, переданные в качестве аргументов конструктора его widget. Вы можете использовать модель или класс контроллера, или PageStorage, чтобы хранить информацию о прогрессе пользователя, если вы не хотите полного сброса.

Вот пример приложения, которое демонстрирует эти концепции.

screen 1 screen 2 screen 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,
          ),
        ],
      ),
    );
  }
}

Ответ 2

Есть абстрактный вызывающий класс WidgetsBindingObserver

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

в

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

есть "государство", можно управлять как

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;
}