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

Flutter登录页与主页切换异常:非手动热重载无法显示页面

Flutter Login/Home Page Auto-Switch Issue Fix

Hey there, let's break down why your login and home pages aren't switching automatically and fix this step by step.

The Root Cause

Looking at your code, two key issues are causing this problem:

  1. Asynchronous Storage Initialization: Your StorageUtil.getInstance() is an async operation, but you're calling runApp() immediately after it without waiting for it to complete. When the Wrapper first builds, the storage hasn't finished initializing yet, so StorageUtil.getString('access_token') returns null—hence it shows the login page. Only when you hot reload, the storage is already initialized, so it reads the token correctly and shows the home page.
  2. No State Refresh on Token Update: After a successful login, you store the token but don't trigger a rebuild of the Wrapper component. That means it stays on the login page until you manually reload.

Fixed Code Examples

Step 1: Wait for Storage Initialization in Main

First, modify your main function to wait for the storage to finish initializing before running the app:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await StorageUtil.getInstance(); // Wait for storage to be ready
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Wrapper(),
    );
  }
}

Step 2: Update Wrapper to Handle Token Changes

Rewrite the Wrapper to use a FutureBuilder for initial token loading, and add a way to refresh the state when the token is updated after login:

class Wrapper extends StatefulWidget {
  const Wrapper({super.key});

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

class _WrapperState extends State<Wrapper> {
  late Future<String?> _tokenFuture;

  @override
  void initState() {
    super.initState();
    // Fetch token once when the widget initializes
    _tokenFuture = Future.value(StorageUtil.getString('access_token'));
  }

  // Call this method to refresh the token state after login
  void _refreshToken() {
    setState(() {
      _tokenFuture = Future.value(StorageUtil.getString('access_token'));
    });
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<String?>(
      future: _tokenFuture,
      builder: (context, snapshot) {
        // Show loading while we wait for the token
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Scaffold(
            body: Center(child: CircularProgressIndicator()),
          );
        }

        final token = snapshot.data;
        if (token != null && token.isNotEmpty) {
          print('filled $token');
          return const Home();
        } else {
          print('empty $token');
          // Pass the refresh method to Authenticate so it can trigger a rebuild after login
          return Authenticate(onLoginSuccess: _refreshToken);
        }
      },
    );
  }
}

Step 3: Trigger Refresh in Authenticate Component

Update your Authenticate component to call the refresh method once the login is successful and the token is stored:

// Inside your Authenticate widget, add a callback parameter
class Authenticate extends StatelessWidget {
  final VoidCallback? onLoginSuccess;

  const Authenticate({super.key, this.onLoginSuccess});

  // Example login button press handler
  void _handleLogin() async {
    // Perform your login API call here
    // ...

    // After successful login, store the token
    await StorageUtil.putString('access_token', 'your_new_token');
    
    // Trigger the wrapper to refresh its state
    onLoginSuccess?.call();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Your login UI here
      body: Center(
        child: ElevatedButton(
          onPressed: _handleLogin,
          child: const Text('Login'),
        ),
      ),
    );
  }
}

Why This Works

  • We wait for the storage to initialize before running the app, so the first token read is accurate.
  • The FutureBuilder handles the initial loading state and ensures we only render the correct page once we have the token.
  • The _refreshToken method triggers a rebuild of the Wrapper when the token is updated, so the page switches automatically after login without needing a hot reload.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 22:12:57