Flutter - Navigator.pushReplacementNamed 显示相同的页面

Flutter - Navigator.pushReplacementNamed show the same page

我有一个简单的应用程序,它有一个 OnBoarding 部分,最后我只想用主页替换当前屏幕。

我安装了 this package 以避免自己重新创建入职逻辑并且似乎运行良好,但无法弄清楚为什么最后我实现 onDone 功能时它向我展示同屏。

这是我的 main.dart

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

// Application
import './theme.dart';
import './routes.dart';
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

  bool shoudShowOnboardingPage =
      sharedPreferences.getBool('shoudShowOnboardingPage') ?? true;

  runApp(
    MyApp(
      shouldShowOnBoardingScreen: shoudShowOnboardingPage,
    ),
  );
}

class MyApp extends StatelessWidget {
  final bool shouldShowOnBoardingScreen;

  MyApp({
    this.shouldShowOnBoardingScreen,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return OrientationBuilder(
        builder: (context, orientation) {
          SizerUtil().init(constraints, orientation);
          return MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'My app',
            theme: themeData,
            home: shouldShowOnBoardingScreen
                ? OnBoardingScreen()
                : HomePageScreen(),
            onGenerateRoute: RouteGenerator.generateRoute,
          );
        },
      );
    });
  }
}

这是我的 routes.dart

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

// Application
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';

class RouteGenerator {
  static const String homePage = '/';
  static const String onBoardingPage = '/onboarding';

  RouteGenerator._();

  static Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case homePage:
        return MaterialPageRoute(
          builder: (_) => HomePageScreen(),
        );

      case onBoardingPage:
        return MaterialPageRoute(
          builder: (_) => OnBoardingScreen(),
        );


      default:
        throw FormatException('Route not found');
    }
  }
}

My onBoarding(存储库仅定义页面的标题、body 和图像):

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sizer/sizer.dart';

// Application
import '../../repositories/onboarding/onboarding_repository.dart';
import '../../models/onboarding/onboarding_page.dart';
import '../../routes.dart';

class OnBoardingScreen extends StatelessWidget {
  final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

  @override
  Widget build(BuildContext context) {
    OnBoardingRepository onBoardingRepository = OnBoardingRepository();

    return Scaffold(
      body: IntroductionScreen(
        globalBackgroundColor: Colors.black,
        pages: List.generate(
          onBoardingRepository.pages.length,
          (index) =>
              buildPageViewModel(onBoardingRepository.pages[index], context),
        ),
        showSkipButton: true,
        skip: Text(
          'Salta',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
        next: const Icon(
          Icons.arrow_forward,
          color: Colors.white,
        ),
        done: Container(
          padding: const EdgeInsets.symmetric(
            horizontal: 20,
            vertical: 6,
          ),
          decoration: BoxDecoration(
            color: Theme.of(context).primaryColor,
            border: Border.all(
              color: Theme.of(context).primaryColor,
            ),
            borderRadius: BorderRadius.all(
              Radius.circular(20),
            ),
          ),
          child: Text(
            'Fine',
            style: TextStyle(
              color: Colors.white,
            ),
          ),
        ),
        onDone: () async {
          final SharedPreferences sharedPreferences = await _prefs;
          sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
            Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
          });
        },
        dotsDecorator: DotsDecorator(
          activeColor: Theme.of(context).primaryColor,
          size: const Size.square(10.0),
          activeSize: const Size(20.0, 10.0),
          color: Colors.white,
          spacing: const EdgeInsets.symmetric(horizontal: 3.0),
          activeShape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(25.0),
          ),
        ),
      ),
    );
  }

  PageViewModel buildPageViewModel(
      OnBoardingPage onBoardingPage, BuildContext context) {
    return PageViewModel(
      title: onBoardingPage.title,
      body: onBoardingPage.body,
      image: Padding(
        padding: EdgeInsets.only(top: 10.0.h),
        child: Center(
          child: SvgPicture.asset(
            onBoardingPage.image,
            height: 60.0.w,
          ),
        ),
      ),
      decoration: PageDecoration(
        titleTextStyle: TextStyle(
          fontSize: 16.0.sp,
          fontWeight: FontWeight.w700,
          color: Theme.of(context).primaryColor,
        ),
        bodyTextStyle: TextStyle(fontSize: 13.0.sp, color: Colors.white),
      ),
    );
  }
}

这里是 home.dart

import 'package:flutter/material.dart';

class HomePageScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('hello'),
      ),
    );
  }
}

入门部分运行良好,我可以看到页面,浏览它们。问题是当我按下 done 按钮并调用 onDone 函数时,它从头开始一次又一次地显示入职屏幕。
我期望的是在我为我的 shoudShowOnboardingPage 设置设置布尔值后删除登机屏幕并将其替换为主页。

这里有一段代码不符合我的预期:

onDone: () async {
        final SharedPreferences sharedPreferences = await _prefs;
        sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
        Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
   });
},

我错过了什么?

因为您在 MaterialApp 中指定了 home 小部件,当您导航到空 \ 路线时,它将再次显示 home 小部件。

我建议您 MaterialApp 使用 initialRoute

MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'My app',
   theme: themeData,
   initialRoute: shouldShowOnBoardingScreen
            ? RouteGenerator.onBoardingPage
            : RouteGenerator.home,
   onGenerateRoute: RouteGenerator.generateRoute,
)