web-dev-qa-db-ja.com

FlutterのウィジェットのonResume()およびonPause()

現在、ウィジェットには、ウィジェットが初めて作成されたときにトリガーされるiniteState()と、ウィジェットが破棄されたときにトリガーされるdispose()のみがあります。ウィジェットがフォアグラウンドに戻ったときを検出する方法はありますか?また、別のウィジェットがフォアグラウンドになったために、ウィジェットがバックグラウンドに移動しようとしているときAndroidではonResumeとonPauseがトリガーされ、iosではviewWillAppearとviewWillDisappearがトリガーされます。

14
user3217522

これを行いたい最も一般的なケースは、アニメーションを実行していて、バックグラウンドでリソースを消費したくない場合です。その場合、StateTickerProviderStateMixinで拡張し、Statevsync引数としてAnimationControllerを使用する必要があります。 Flutterは、Stateが表示されている場合にのみ、アニメーションコントローラーのリスナーを呼び出します。

Stateが他のコンテンツによって隠されているときにPageRouteにあるPageRoutesを破棄する場合は、maintainStatefalse 引数をPageRouteコンストラクターに渡すことができます。これを行うと、Stateは非表示になるとそれ自体(およびその子)をリセットし、initStateにコンストラクター引数として渡されるプロパティを使用してwidgetで再構築する必要があります。モデルまたはコントローラークラス、または PageStorage を使用して、完全にリセットしたくない場合にユーザーの進行情報を保持できます。

これらの概念を示すサンプルアプリを次に示します。

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

抽象クラスの呼び出し元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;
}
31
Mamnarock