如何在应用重新启动之间保存和恢复 Flutter ListView 的滚动位置?
Posted
技术标签:
【中文标题】如何在应用重新启动之间保存和恢复 Flutter ListView 的滚动位置?【英文标题】:How can I save and restore the scroll position of a Flutter ListView between app restarts? 【发布时间】:2020-01-14 02:35:15 【问题描述】:我想保留 ListView 的滚动位置,以便在应用重新启动之间恢复。
所以我猜它应该使用shared_preferences
之类的东西保存在磁盘上(在 ios 上的 NSUserDefaults 和 android 上的 SharedPreferences 中)
是否有内置方式(或插件)可以做到这一点?
如果我必须手动进行,我应该何时保存滚动位置? (在原生 Android 应用程序中,我会在 onPause
Activity 生命周期方法中执行此操作。)
我搜索了很多,但似乎找不到任何说明如何保存和恢复 ListView 滚动位置的帖子或示例代码。
【问题讨论】:
为什么不在 Android 中的 onSaveInstanceState 中? pub.dev/packages/shared_preferences 有什么问题? @Eugene shared_preferences 没有任何问题。我在问是否有一种内置方式(或插件)已经可以做到这一点。 【参考方案1】:如果我必须手动执行,我应该何时保存滚动位置? (在原生 Android 应用程序中,我会在 onPause Activity 生命周期方法中执行此操作。)
您可以使用 mixin WidgetsBindingObserver 通过监听 AppLifecycleState 来检测您的应用何时进入后台以及何时进入前台
可观察的生命周期事件是:
paused — 应用程序当前对用户不可见,不响应用户输入,并且在后台运行。就像Android中的onPause()
inactive — 应用程序处于非活动状态并且未接收用户输入。 (仅限 IOS)
resumed — 应用程序可见并响应用户输入。就像Android中的onPostResume()
suspending — 应用程序将暂时暂停。 (仅限 Android)
在示例中,我保存日期而不是滚动位置
class _TestPageState extends State<TestPage> with WidgetsBindingObserver
SharedPreferences prefs;
@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'); // resumed, paused, inactive, suspending
if (state == AppLifecycleState.paused)
prefs.setString('date', DateTime.now().toIso8601String());
_TestPageState()
initPrefs();
void initPrefs() async
prefs = await SharedPreferences.getInstance();
print(prefs.getString('date') ?? 'no date');
...
【讨论】:
【参考方案2】:我们现在对 Flutter 中的状态恢复提供了开箱即用的支持。
查看ScrollView
小部件内的restorationId
属性。
查看此链接以了解如何在 Flutter 中实现恢复。
https://dev.to/pedromassango/what-is-state-restoration-and-how-to-use-it-in-flutter-5blm
【讨论】:
【参考方案3】:正如您在问题中所说 - 使用 https://pub.dev/packages/shared_preferences 是最好的选择,因为它使用了处理此类内容的本机方式 - Android 为 SharedPreferences
,iOS 为 NSUserDefaults
。 Android 中的新方法 PersistentBundle
也可以在颤振中使用,但没有适用于 iO 的模拟。你也可以使用各种数据库和文件存储,但在这种情况下会有点过分。
在移动设备上存储滚动状态始终是一项手动任务 - 没有开箱即用的快捷方式 - 所以只有手工制作的东西或库。
您可以将有状态小部件的整个状态存储在那里,然后将其作为一个整体恢复。
【讨论】:
以上是关于如何在应用重新启动之间保存和恢复 Flutter ListView 的滚动位置?的主要内容,如果未能解决你的问题,请参考以下文章
iPhone SDK - 如何在应用程序关闭和重新打开时保存和恢复计时器标签
应用程序重新启动 C++ Visual Studio 时保存编辑控件用户输入和恢复的有效方法