バックグラウンドからの復帰処理を追加したかったので、LifecycleWidgetとライフサイクルを一元管理できるLifecycleServiceを作成しました。
Flutterのライフスタイルを取得するためにはStatefulWidgetを使う必要がありますが、各ページはStatelessWidgetで実装されているため毎度StatefulWidgetを使いたくありません。
なのでLifecycleWidgetでアプリ全体をラップして使用します。
ステートの取得はRxDartを使用して、どこからでもstreamで取得できるようにしています。
この記事の目次
LifecycleService
sink/streamを持つだけのサービスを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; class LifecycleService { static LifecycleService shared = LifecycleService(); /// アプリ全体のライフサイクル AppLifecycleState lifecycleState; final _lifecycleStateSubject = PublishSubject<AppLifecycleState>(); /// アプリ全体のライフサイクルの通知用Stream Stream<AppLifecycleState> get lifecycleState$ => _lifecycleStateSubject.stream; /// アプリ全体のライフサイクルの通知用Sink Sink<AppLifecycleState> get lifecycleStateSink$ => _lifecycleStateSubject.sink; void dispose() { _lifecycleStateSubject.close(); } } |
LifecycleWidget
LifecycleWidgetはStatefulWidgetでできています。
やっていることは単純で、sinkで各ステートをサービスに流しているだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import 'package:flutter/material.dart'; import 'package:app/service/app/lifecycle_service.dart'; /// ライフサイクル用のwidget class LifecycleWidget extends StatefulWidget { final Widget child; LifecycleWidget({Key key, this.child}) : super(key: key); _LifeCycleWidgetState createState() => _LifeCycleWidgetState(); } class _LifeCycleWidgetState extends State<LifecycleWidget> with WidgetsBindingObserver { @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { print('state = $state'); //ステートをLifecycleServiceのストリームに流す switch (state) { case AppLifecycleState.resumed: LifecycleService.shared.lifecycleStateSink$.add(AppLifecycleState.resumed); break; case AppLifecycleState.inactive: LifecycleService.shared.lifecycleStateSink$.add(AppLifecycleState.inactive); break; case AppLifecycleState.paused: LifecycleService.shared.lifecycleStateSink$.add(AppLifecycleState.paused); break; case AppLifecycleState.detached: LifecycleService.shared.lifecycleStateSink$.add(AppLifecycleState.detached); break; } } @override Widget build(BuildContext context) { return Container( child: widget.child, ); } } |
アプリ全体をLifecycleWidgetでラップする
main.dartでアプリ全体をLifecycleWidgetでラップしてあげます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import 'package:flutter/material.dart'; import 'package:app/utilities/LifecycleWidget.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return LifecycleWidget( child: MaterialApp( title: 'Flutter Demo', theme: ThemeData.dark(), home: MainPage(), ), ); } } |
各ページでの使用方法
あとは使用したいところでstreamをlistenしてあげるだけです。どこからでも呼べるので便利ですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
LifecycleService.shared.lifecycleState$.listen((AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: print('resumed'); break; case AppLifecycleState.inactive: print('inactive'); break; case AppLifecycleState.paused: print('paused'); break; case AppLifecycleState.detached: print('detached'); break; } }); |
コメント