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

如何使用SharedPreferences控制Flutter应用的初始路由?

如何根据SharedPreferences状态控制Flutter应用初始路由?

你可以通过两种实用方式实现需求:在应用启动前异步获取登录状态,或者用FutureBuilder在页面构建时动态处理状态,具体实现如下:

方法一:在main函数中提前获取状态(推荐)

这种方式会在应用启动前先拿到登录状态,直接传递给根组件设置初始路由,逻辑简洁直接:

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

void main() async {
  // 必须调用此方法,确保Flutter初始化完成后再执行异步操作
  WidgetsFlutterBinding.ensureInitialized();
  
  // 获取SharedPreferences实例并读取登录状态
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  bool isLoggedIn = prefs.getBool('loggedIn') ?? false; // 首次打开默认未登录

  runApp(MyApp(isLoggedIn: isLoggedIn));
}

class MyApp extends StatelessWidget {
  final bool isLoggedIn;

  const MyApp({super.key, required this.isLoggedIn});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo App',
      // 根据登录状态设置初始路由
      initialRoute: isLoggedIn ? '/home' : '/login',
      routes: {
        '/login': (context) => const LoginPage(),
        '/home': (context) => const HomePage(),
      },
    );
  }
}

// 示例登录页面
class LoginPage extends StatelessWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('登录')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            // 执行登录逻辑后保存状态
            final SharedPreferences prefs = await SharedPreferences.getInstance();
            await prefs.setBool('loggedIn', true);
            
            // 登录成功后替换路由,避免返回登录页
            if (!context.mounted) return;
            Navigator.pushReplacementNamed(context, '/home');
          },
          child: const Text('登录'),
        ),
      ),
    );
  }
}

// 示例首页
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('首页')),
      body: const Center(child: Text('已登录,欢迎使用')),
    );
  }
}

方法二:用FutureBuilder处理异步状态

如果不想把异步逻辑放在main函数里,可以用FutureBuilder在根组件中动态判断页面,还能处理加载状态:

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // 封装获取登录状态的异步方法
  Future<bool> _getLoginStatus() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getBool('loggedIn') ?? false;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo App',
      home: FutureBuilder<bool>(
        future: _getLoginStatus(),
        builder: (context, snapshot) {
          // 状态未返回时显示加载动画
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Scaffold(body: Center(child: CircularProgressIndicator()));
          }
          // 根据状态渲染对应页面
          bool isLoggedIn = snapshot.data ?? false;
          return isLoggedIn ? const HomePage() : const LoginPage();
        },
      ),
      routes: {
        '/login': (context) => const LoginPage(),
        '/home': (context) => const HomePage(),
      },
    );
  }
}

// LoginPage和HomePage代码同方法一,此处省略

注意事项

  • 必须在main函数的异步操作前调用WidgetsFlutterBinding.ensureInitialized(),否则会因Flutter未初始化完成报错。
  • 用?? false处理loggedIn字段不存在的场景(比如用户首次打开应用),确保默认状态为未登录。
  • 登录成功后使用pushReplacementNamed替换路由,而不是普通的push,这样用户点击返回按钮不会回到登录页。

内容的提问来源于stack exchange,提问作者user15723984

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:13:43