Flutter状态恢复与SharedPreference的区别及电商购物车恢复可行性问询
嘿,咱们先把这俩的核心差异唠明白——其实它们根本不是一个赛道的东西:
设计目标天差地别:SharedPreferences(大伙常叫它SP)是持久化本地存储工具,专门存需要长期保留的数据——比如用户的登录token、主题偏好、已经加入购物车的商品(要长期留存的那种)。就算用户把APP后台清了、甚至重启手机,只要没卸载没清缓存,数据还在。而状态恢复是Flutter官方为解决「APP被系统强制回收后,用户操作状态丢失」的问题搞出来的,它管的是临时会话内的状态恢复,比如你正在填地址、选购物车商品,突然APP被系统杀了,重新打开能回到刚才的状态,不用从头再来。
生命周期完全不同:SP的数据跟APP的存储目录绑定,属于「长期存档」;状态恢复的数据是临时的,只绑定当前APP的会话——一旦用户主动划掉APP进程,这些恢复数据就会被清空,不会留到下次打开。
使用方式的自动化程度不一样:SP得你手动读写,比如先
SharedPreferences.getInstance(),再setString存、getString取,时机全靠你自己把控。状态恢复则是Flutter框架帮你包办了大部分脏活,你只要用RestorableProperty这类API标记需要恢复的状态,框架会自动在合适的时机(比如APP进入后台时)保存,在重启时自动恢复,不用你操心时机问题。支持的数据类型有差异:SP只支持基础数据类型(字符串、布尔、整数、浮点数)和简单列表;状态恢复则更灵活,除了基础类型,还能自定义可恢复的对象——只要你实现
RestorableInterface,就能直接恢复自定义的商品对象、订单信息这类复杂数据。
当然可以!不过得分场景用,不能一概而论:
适合用状态恢复的场景
如果用户正在操作购物车——比如选中了几个商品准备结算,这时候APP突然被系统后台回收了,用状态恢复能快速把用户之前选中的商品状态恢复出来,不用用户再重新选一遍,体验直接拉满。这种「临时会话内的操作状态」,正是状态恢复的强项。
必须结合持久化存储的场景
但如果用户希望购物车的商品长期保留(比如今天加了商品,过几天打开APP还能看到),那只靠状态恢复就不行了——因为用户主动退出APP后,状态恢复的数据就没了。这时候得把购物车的核心数据(比如商品ID、数量)持久化存在SP(或者更适合的本地数据库,比如Hive、sqflite)里,然后状态恢复可以在APP重启时,先从持久化存储里读取购物车数据,再恢复用户之前的选中状态,两者配合起来用才完美。
举个实际的代码例子
比如用RestorableList来保存选中的商品ID,实现选中状态的自动恢复:
class CartPage extends StatefulWidget { const CartPage({super.key}); @override State<CartPage> createState() => _CartPageState(); } class _CartPageState extends State<CartPage> with RestorationMixin { // 标记需要恢复的选中商品ID列表 final RestorableList<String> _selectedProductIds = RestorableList<String>([]); @override String get restorationId => 'cart_page'; // 给页面一个恢复ID @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { // 注册需要恢复的状态 registerForRestoration(_selectedProductIds, 'selected_product_ids'); } // 切换商品选中状态 void toggleProductSelection(String productId) { setState(() { if (_selectedProductIds.value.contains(productId)) { _selectedProductIds.value.remove(productId); } else { _selectedProductIds.value.add(productId); } }); } @override Widget build(BuildContext context) { return ListView.builder( itemCount: _cartProducts.length, itemBuilder: (context, index) { final product = _cartProducts[index]; return CheckboxListTile( value: _selectedProductIds.value.contains(product.id), onChanged: (value) { if (value != null) toggleProductSelection(product.id); }, title: Text(product.name), ); }, ); } // 模拟购物车商品数据 final List<Product> _cartProducts = [ Product(id: '1', name: '无线蓝牙耳机'), Product(id: '2', name: '快充移动电源'), ]; } class Product { final String id; final String name; Product({required this.id, required this.name}); }
这个例子里,当APP被系统回收重启后,框架会自动恢复_selectedProductIds的状态,用户之前选中的商品就会被标记为选中状态啦。
内容的提问来源于stack exchange,提问作者Harsh Singh

