Flutter 封装:最佳实践 —— AppLifecycleState 状态监听封装

2,303 阅读2分钟

备注:Flutter v3.13 版本以下推荐使用;以上使用官方实现 AppLifecycleListener;

一、需求来源

项目中多页面需要同时监听 AppLifecycleState 根据状态实现不同的业务逻辑;尝试多种实现,使用起来比较麻烦,为了开发效率,随封装一个。代码不复杂,核心在于极简的封装方法。

效果如下:

//进入后台
[log] 2024-05-31 10:50:53.133135 AppTabPage inactive
[log] 2024-05-31 10:50:53.134143 AppLifecycleStateObserverDemo inactive
[log] 2024-05-31 10:50:53.871600 AppTabPage hidden
[log] 2024-05-31 10:50:53.871889 AppLifecycleStateObserverDemo hidden
[log] 2024-05-31 10:50:53.872113 AppTabPage paused
[log] 2024-05-31 10:50:53.872335 AppLifecycleStateObserverDemo paused

//进入前台
[log] 2024-05-31 10:51:06.348528 AppTabPage hidden
[log] 2024-05-31 10:51:06.348764 AppLifecycleStateObserverDemo hidden
[log] 2024-05-31 10:51:06.348977 AppTabPage inactive
[log] 2024-05-31 10:51:06.349141 AppLifecycleStateObserverDemo inactive
[log] 2024-05-31 10:51:06.625449 AppTabPage resumed
[log] 2024-05-31 10:51:06.626024 AppLifecycleStateObserverDemo resumed

//上划杀掉 app
[log] 2024-05-31 10:51:33.060508 AppTabPage detached
[log] 2024-05-31 10:51:33.060692 AppLifecycleStateObserverDemo detached

// AppTabPage 为主页面;
// AppLifecycleStateObserverDemo 为特定业务界面;

二、使用示例

import 'package:flutter/material.dart';
import 'package:flutter_templet_project/util/AppLifecycleObserver.dart';
import 'package:flutter_templet_project/util/debug_log.dart';

class AppLifecycleStateObserverDemo extends StatefulWidget {

  AppLifecycleStateObserverDemo({
    super.key, 
    this.title
  });

  final String? title;

  @override
  State<AppLifecycleStateObserverDemo> createState() => _AppLifecycleStateObserverDemoState();
}

class _AppLifecycleStateObserverDemoState extends State<AppLifecycleStateObserverDemo> with
    AppLifecycleObserverMixin {

  final _scrollController = ScrollController();


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title ?? "$widget"),
        actions: ['done',].map((e) => TextButton(
          child: Text(e,
            style: TextStyle(color: Colors.white),
          ),
          onPressed: () => debugPrint(e),)
        ).toList(),
      ),
      body: buildBody(),
    );
  }

  buildBody() {
    return Scrollbar(
      controller: _scrollController,
      child: SingleChildScrollView(
        controller: _scrollController,
        child: Column(
          children: [
            Text("$widget"),
          ],
        ),
      ),
    );
  }

  /*************** AppLifecycleObserverMixin ***************/
  @override
  void onAppLifecycleStateChanged(AppLifecycleState state) {
    ddlog("$widget onAppLifecycleStateChanged $state");
  }

}

三、源码

1、AppLifecycleObserver 源码

/// app 前后台生命周期函数监听
class AppLifecycleObserver extends WidgetsBindingObserver{

  AppLifecycleObserver({
    required this.onStateChanged,
  });


  final ValueChanged<AppLifecycleState> onStateChanged;


  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    onStateChanged(state);
  }
}

2、AppLifecycleObserverMixin 源码

/// app 前后台生命周期函数混入封装
mixin AppLifecycleObserverMixin<T extends StatefulWidget> on State<T>{
  late final _lifecycleEvent = AppLifecycleObserver(
    onStateChanged: onAppLifecycleStateChanged,
  );

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(_lifecycleEvent);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(_lifecycleEvent);
    super.dispose();
  }

  void onAppLifecycleStateChanged(AppLifecycleState state) {
    throw UnimplementedError("❌: $this 未实现 onAppLifecycleStateChanged");
    // debugPrint('onStateChanged didChangeAppLifecycleState state');
  }

}

四、总结

1、Flutter 3.13 之后官方实现了一个 AppLifecycleListener

使用效果和 AppLifecycleObserverMixin 相同,基于官方优先原则(未来维护性考虑),建议大家使用官方 AppLifecycleListener实现功能。

class AppLifecycleListener with WidgetsBindingObserver, Diagnosticable {
  /// Creates an [AppLifecycleListener].
  AppLifecycleListener({
    WidgetsBinding? binding,
    this.onResume,
    this.onInactive,
    this.onHide,
    this.onShow,
    this.onPause,
    this.onRestart,
    this.onDetach,
    this.onExitRequested,
    this.onStateChange,
  })  : binding = binding ?? WidgetsBinding.instance,
        _lifecycleState = (binding ?? WidgetsBinding.instance).lifecycleState {
    this.binding.addObserver(this);
  }
  。。。
2、AppLifecycleObserverMixin 生命周期方法如果未实现会日志报错,提示到具体页面;

github