Réponse courte : non, ce n'est pas possible, bien que j'ai observé un comportement différent pour l'écran se mettant en veille. Le code suivant vous aidera à comprendre les différents états d'une application Flutter sur Android, testée avec ces versions de Flutter et Flutter Engine :
- Révision du cadre b339c71523 (il y a 6 heures), 2017-02-04 00:51:32
- Révision du moteur cd34b0ef39
Créez une nouvelle application Flutter, et remplacez le contenu du fichier lib/main.dart
avec ce code :
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class LifecycleWatcher extends StatefulWidget {
@override
_LifecycleWatcherState createState() => new _LifecycleWatcherState();
}
class _LifecycleWatcherState extends State<LifecycleWatcher>
with WidgetsBindingObserver {
AppLifecycleState _lastLifecyleState;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void onDeactivate() {
super.deactivate();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print("LifecycleWatcherState#didChangeAppLifecycleState state=${state.toString()}");
setState(() {
_lastLifecyleState = state;
});
}
@override
Widget build(BuildContext context) {
if (_lastLifecyleState == null)
return new Text('This widget has not observed any lifecycle changes.');
return new Text(
'The most recent lifecycle state this widget observed was: $_lastLifecyleState.');
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter App Lifecycle'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _timerCounter = 0;
// ignore: unused_field only created once
Timer _timer;
_MyHomePageState() {
print("_MyHomePageState#constructor, creating new Timer.periodic");
_timer = new Timer.periodic(
new Duration(milliseconds: 3000), _incrementTimerCounter);
}
void _incrementTimerCounter(Timer t) {
print("_timerCounter is $_timerCounter");
setState(() {
_timerCounter++;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(config.title),
),
body: new Block(
children: [
new Text(
'Timer called $_timerCounter time${ _timerCounter == 1 ? '' : 's' }.',
),
new LifecycleWatcher(),
],
),
);
}
}
Au lancement de l'application, la valeur de _timerCounter est incrémentée toutes les 3s. Un champ de texte situé sous le compteur indique toute AppLifecycleState pour l'application Flutter, vous verrez la sortie correspondante dans le journal de débogage de Flutter, par exemple :
[raju@eagle:~/flutter/helloworld]$ flutter run
Launching lib/main.dart on SM N920S in debug mode...
Building APK in debug mode (android-arm)... 6440ms
Installing build/app.apk... 6496ms
I/flutter (28196): _MyHomePageState#constructor, creating new Timer.periodic
Syncing files to device...
I/flutter (28196): _timerCounter is 0
To hot reload your app on the fly, press "r" or F5. To restart the app entirely, press "R".
The Observatory debugger and profiler is available at: http://127.0.0.1:8108/
For a more detailed help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.
I/flutter (28196): _timerCounter is 1
I/flutter (28196): LifecycleWatcherState#didChangeAppLifecycleState state=AppLifecycleState.paused
I/flutter (28196): _timerCounter is 2
I/flutter (28196): _timerCounter is 3
I/flutter (28196): LifecycleWatcherState#didChangeAppLifecycleState state=AppLifecycleState.resumed
I/flutter (28196): _timerCounter is 4
I/flutter (28196): LifecycleWatcherState#didChangeAppLifecycleState state=AppLifecycleState.paused
I/flutter (28196): _timerCounter is 5
I/flutter (28196): _timerCounter is 6
I/flutter (28196): _timerCounter is 7
I/flutter (28196): LifecycleWatcherState#didChangeAppLifecycleState state=AppLifecycleState.resumed
I/flutter (28196): LifecycleWatcherState#didChangeAppLifecycleState state=AppLifecycleState.paused
I/flutter (28196): _timerCounter is 8
I/flutter (28196): _MyHomePageState#constructor, creating new Timer.periodic
I/flutter (28196): _timerCounter is 0
I/flutter (28196): _timerCounter is 1
Pour la sortie du journal ci-dessus, voici les étapes que j'ai suivies :
- Lancer l'application avec
flutter run
- Passage à une autre application (_timerCounter valeur 1)
- Retour à l'application Flutter (valeur 3 du _timerCounter)
- Appui sur le bouton d'alimentation, l'écran s'est éteint (_timerCounter valeur 4)
- Téléphone déverrouillé, reprise de l'application Flutter (_timerCounter valeur 7)
- Appuyez sur la touche retour du téléphone (la valeur de _timerCounter n'a pas changé). C'est à ce moment que l'activité FlutterActivity est détruite et que la VM Dart est également isolée.
- Reprise de l'application Flutter (la valeur de _timerCounter est à nouveau 0)
Passage d'une application à l'autre, en appuyant sur le bouton d'alimentation ou le bouton arrière
Lorsque vous passez à une autre application ou que vous appuyez sur le bouton d'alimentation pour éteindre l'écran, le minuteur continue de fonctionner. Mais si vous appuyez sur le bouton retour alors que l'application Flutter a le focus, l'activité est détruite, et avec elle l'isolat Dart. Vous pouvez tester cela en vous connectant à l'application Observatoire de Dart lorsque vous passez d'une application à l'autre, ou lorsque vous tournez l'écran. L'Observatoire montre une application Flutter active, Isolate, en cours d'exécution. Mais lorsque vous appuyez sur le bouton retour, l'Observatoire n'affiche pas Isolate en cours d'exécution. Ce comportement a été confirmé sur un Galaxy Note 5 fonctionnant sous Android 6.x, et un Nexus 4 fonctionnant sous Android 4.4.x.
Cycle de vie des applications Flutter et cycle de vie Android Pour la couche de widgets de Flutter, seul l'élément interrompu et a repris Les états sont exposés. Destroy est géré par Activité Android pour une application Android Flutter :
/**
* @see android.app.Activity#onDestroy()
*/
@Override
protected void onDestroy() {
if (flutterView != null) {
flutterView.destroy();
}
super.onDestroy();
}
Comme la VM Dart d'une application Flutter est exécutée dans l'activité, la VM sera arrêtée chaque fois que l'activité sera détruite.
Logique du code du moteur Flutter
Cela ne répond pas directement à votre question, mais vous donnera des informations de base plus détaillées sur la façon dont le moteur Flutter gère les changements d'état pour Android.
En examinant le code du moteur de Flutter, il est évident que la boucle d'animation est mise en pause lorsque la fonction FlutterActivity reçoit l'Android Activité#en#pause événement. Lorsque l'application passe en interrompu l'état, selon le commentaire de la source ici il se passe ce qui suit :
" L'application n'est pas actuellement visible par l'utilisateur. Lorsque l'application est dans cet état, le moteur n'appelle pas le rappel [onBeginFrame]."
D'après mes tests, la minuterie continue de fonctionner même si le rendu de l'interface utilisateur est mis en pause, ce qui est logique. Il serait bon d'envoyer un événement dans la couche de widgets en utilisant la fonction WidgetsBindingObserver lorsque l'activité est détruite, de sorte que les développeurs peuvent s'assurer de stocker l'état de l'application Flutter jusqu'à ce que l'activité soit reprise.
2 votes
La vraie question est peut-être la suivante : est-il possible d'exécuter du code en arrière-plan (par exemple, des minuteries) pour une application Flutter lorsque l'activité est détruite ? Dans mon cas, le minuteur continuerait à fonctionner même si j'éteins l'écran (voir réponse ci-dessous).
0 votes
Vous ne pouvez pas faire cela complètement du côté client, je pense que vous devez lancer une minuterie sur le serveur et la synchroniser avec le front-end, quelque chose comme un flux de données de sorte que lorsque le téléphone se met en veille et revient à l'application, il devrait commencer à partir de la minuterie actuelle sur le serveur.
0 votes
Vous pouvez également consulter stackoverflow.com/a/59057145/6668797 pour d'autres moyens