如何保存 PageView 的索引并在重新打开应用程序时加载它?

How to save an index of PageView and load it when reopening the app?

我想保存 PageView 的索引并在重新打开应用程序时加载它。
例如,如果用户在第 2 页关闭应用程序,则应在第 2 页启动应用程序。

我尝试使用 shared_preferences 和提供商来实现此功能。
但是,应用程序始终从第 1 页开始,可能是因为 PageControllerinitialPage 被初始化为 0BottomNavigationbarBottomNavigationBarItem 按预期工作。
如何保存 PageView 的索引并在用户重新打开应用程序时加载它?

main.dart

import 'package:flutter/material.dart';
import 'package:test/home_screen.dart';
import 'package:test/provider_data.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => ProviderData(),
      child: MaterialApp(
        title: 'test',
        home: const HomeScreen(),
      ),
    );
  }
}

home_screen.dart

import 'package:flutter/material.dart';
import 'package:test/page1.dart';
import 'package:test/page2.dart';
import 'package:test/provider_data.dart';
import 'package:provider/provider.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final List<Widget> _pageList = const [
    Page1(),
    Page2(),
  ];

  final PageController _pageController = PageController();

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Consumer<ProviderData>(
          builder: (context, providerData, child) {
            return PageView(
              controller: _pageController,
              children: _pageList,
              onPageChanged: (index) {
                providerData.changePageIndex(index);
              },
            );
          },
        ),
      ),
      bottomNavigationBar: Consumer<ProviderData>(
        builder: (context, providerData, child) {
          return BottomNavigationBar(
            onTap: (index) {
              _pageController.animateToPage(
                index,
                duration: const Duration(microseconds: 10),
                curve: Curves.linear,
              );
              providerData.changePageIndex(index);
            },
            type: BottomNavigationBarType.fixed,
            currentIndex: providerData.pageIndex!,
            items: const [
              BottomNavigationBarItem(
                icon: Icon(Icons.search),
                label: 'Page 1',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                label: 'Page 2',
              ),
            ],
          );
        },
      ),
    );
  }
}

provider_data.dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ProviderData extends ChangeNotifier {
  SharedPreferences? prefs;
  final String pageIndexKey = 'pageIndex';
  int? _pageIndex;
  int? get pageIndex => _pageIndex;

  ProviderData() {
    _pageIndex = 0;
    _loadFromPrefs();
  }

  _initPrefs() async {
    prefs ??= await SharedPreferences.getInstance();
  }

  _loadFromPrefs() async {
    await _initPrefs();
    _pageIndex = prefs!.getInt(pageIndexKey) ?? 0;
    notifyListeners();
  }

  _savePageIndexToPrefs({required String key, required int value}) async {
    await _initPrefs();
    prefs!.setInt(key, value);
  }

  void changePageIndex(int newPageIndex) {
    _pageIndex = newPageIndex;
    _savePageIndexToPrefs(key: pageIndexKey, value: _pageIndex!);
    notifyListeners();
  }
}

在 initState() 中检索页面视图的索引

首先,您应该将_loadFromPrefs()方法更改为public,然后在initState()方法中调用此方法,并将返回值赋值给PageContoller(initialPage: value),格式如下:

在home_screen.dart

  late PageController _pageController;

  @override
  void initState() {
    super.initState();
    ProviderData().loadFromPrefs().then((value) {
      _pageController = PageController(initialPage: value);
    });
  }

在provider_data.dart

  loadFromPrefs() async {
    await _initPrefs();
    _pageIndex = prefs!.getInt(pageIndexKey) ?? 0;
    notifyListeners();
  }