В настоящее время виджет имеет только initeState(), который запускается с первого раза, когда создается виджет, и dispose(), который запускается при уничтожении виджета. Есть ли способ обнаружить, когда виджет возвращается на передний план? и когда виджет вот-вот перейдет на задний план, потому что еще один виджет был наложен? Это эквивалент onResume и onPause запускается для Android, а viewWillAppear и viewWillDisappear для ios
OnResume() и onPause() для виджетов на Flutter
Ответ 1
Наиболее распространенный случай, когда вы захотите сделать это, если у вас запущена анимация и вы не хотите использовать ресурсы в фоновом режиме. В этом случае вы должны расширить свой State
с помощью TickerProviderStateMixin
и использовать свой State
в качестве аргумента vsync
для AnimationController
. Flutter позаботится о том, чтобы вызывать слушателей контроллера анимации только тогда, когда видимо ваше State
.
Если вы хотите, чтобы State
, которые живут в вашем PageRoute
, чтобы быть утилизированы, когда PageRoute
затемняется другим содержимым, вы можете передать maintainState
аргумент false
для вашего PageRoute
конструктора. Если вы сделаете это, ваше State
сбросит себя (и его дочерние initState
), когда оно будет скрыто, и ему придется пересоздать себя в initState
используя свойства, переданные в качестве аргументов конструктора его widget
. Вы можете использовать модель или класс контроллера, или PageStorage
, чтобы хранить информацию о прогрессе пользователя, если вы не хотите полного сброса.
Вот пример приложения, которое демонстрирует эти концепции.
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;
}