You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:Android杀后台后如何按需恢复表单与应用状态?

解决方案

一、仅在系统销毁Activity时持久化Bloc状态

hydrated_bloc默认全局持久化状态,要实现仅在App被后台杀死时保留状态,核心是区分正常页面退出和系统强制销毁两种场景:

  1. 监听App生命周期,标记销毁状态
    在表单页面混入WidgetsBindingObserver,通过生命周期状态判断是否是系统销毁:

    class FormPage extends StatefulWidget {
      @override
      _FormPageState createState() => _FormPageState();
    }
    
    class _FormPageState extends State<FormPage> with WidgetsBindingObserver {
      bool _isSystemDestroyed = false;
      final _formKey = GlobalKey<FormBuilderState>();
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
    
      @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
        // 当App完全脱离前台(被系统销毁时会触发此状态)
        if (state == AppLifecycleState.detached) {
          _isSystemDestroyed = true;
        }
      }
    
      @override
      void dispose() {
        // 正常关闭页面时,清除Bloc的持久化数据
        if (!_isSystemDestroyed) {
          context.read<FormBloc>().clear();
          // 同时清除路由和表单数据的持久化记录
          _clearPersistedData();
        }
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      Future<void> _clearPersistedData() async {
        final prefs = await SharedPreferences.getInstance();
        await prefs.remove('last_route');
        await prefs.remove('form_data');
      }
    }
    
  2. 配合Bloc控制持久化逻辑
    给你的FormBloc添加开关,仅在系统销毁时允许序列化状态:

    class FormBloc extends HydratedBloc<FormEvent, FormState> {
      bool shouldPersist = false;
    
      FormBloc() : super(FormState.initial()) {
        on<FormDataUpdated>((event, emit) {
          emit(state.copyWith(formData: event.values));
        });
      }
    
      @override
      FormState? fromJson(Map<String, dynamic> json) {
        return shouldPersist ? FormState.fromJson(json) : null;
      }
    
      @override
      Map<String, dynamic>? toJson(FormState state) {
        return shouldPersist ? state.toJson() : null;
      }
    }
    

    在页面的didChangeAppLifecycleState中设置开关:

    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
      if (state == AppLifecycleState.detached) {
        _isSystemDestroyed = true;
        context.read<FormBloc>().shouldPersist = true;
      }
    }
    

二、应用重启后自动跳转表单页

通过持久化路由信息,在App启动时读取并设置初始路由:

  1. 保存当前路由
    在表单页面initState中持久化路由名称:

    @override
    void initState() {
      super.initState();
      _saveCurrentRoute();
    }
    
    Future<void> _saveCurrentRoute() async {
      final prefs = await SharedPreferences.getInstance();
      // 替换为你的auto_route路由名
      await prefs.setString('last_route', Routes.longFormPage);
    }
    
  2. 启动时跳转目标页面
    在App入口初始化路由前读取持久化数据:

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      final prefs = await SharedPreferences.getInstance();
      final lastRoute = prefs.getString('last_route');
    
      // 初始化auto_route时传入初始路由
      final appRouter = AppRouter(initialRoute: lastRoute);
    
      runApp(MyApp(router: appRouter));
    }
    

三、填充FormBuilder的表单数据

核心是让表单数据和持久化层同步,有两种实现方式:

  1. 同步表单数据到Bloc状态
    利用FormBuilder的onChanged回调,实时将表单数据同步到Bloc,重启后从Bloc状态恢复:

    FormBuilder(
      key: _formKey,
      // 从Bloc状态读取初始值
      initialValue: context.watch<FormBloc>().state.formData,
      onChanged: (values) {
        // 实时更新Bloc状态
        context.read<FormBloc>().add(FormDataUpdated(values));
      },
      // 表单字段
      child: Column(
        children: [
          FormBuilderTextField(name: 'username'),
          FormBuilderDropdown(name: 'gender'),
          // ...其他字段
        ],
      ),
    )
    
  2. 单独持久化表单数据
    如果不想依赖Bloc,可直接用SharedPreferences存储表单数据:

    // 系统销毁时保存表单数据
    Future<void> _saveFormData() async {
      if (_formKey.currentState?.validate() ?? false) {
        final prefs = await SharedPreferences.getInstance();
        await prefs.setString(
          'form_data',
          jsonEncode(_formKey.currentState!.value),
        );
      }
    }
    
    // 页面初始化时加载数据
    @override
    void initState() {
      super.initState();
      _loadFormData();
    }
    
    Future<void> _loadFormData() async {
      final prefs = await SharedPreferences.getInstance();
      final dataStr = prefs.getString('form_data');
      if (dataStr != null) {
        final formData = jsonDecode(dataStr) as Map<String, dynamic>;
        _formKey.currentState?.patchValue(formData);
      }
    }
    

    记得在didChangeAppLifecycleState中调用_saveFormData()。

关键验证点

  • 用Android Studio的「Stop Process」模拟后台杀死应用,验证状态恢复和页面跳转是否正常
  • 测试正常返回页面的场景,确保持久化数据被清除,不会干扰下次进入表单

内容的提问来源于stack exchange,提问作者Szymon Głowacki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:49:55