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

Flutter应用登出时Token未清除及空值异常问题咨询

Fixing Logout & Token Management Issues in Your Flutter App

Let's walk through solving your logout and null-check error problems step by step, plus some code optimizations to make your auth flow more reliable.

1. Fix the Null Check Exception

The error Unhandled Exception: Null check operator used on a null value comes from using the bang operator (!) on a potentially null value in your Network provider. When you log out, the token is removed from SharedPreferences, but your code still tries to force a non-null value.

Update the authToken getter and getToken method in your Network class:

Future<String?> get authToken async { 
  SharedPreferences localStorage = await SharedPreferences.getInstance(); 
  return _authToken = localStorage.getString('token'); // Remove the ! operator
} 

getToken() async { 
  SharedPreferences localStorage = await SharedPreferences.getInstance(); 
  token = localStorage.getString('token'); // Remove the ! operator
}

2. Properly Update Provider State on Logout

Right now, you're removing the token from local storage but not updating your provider's internal state. This means the app still thinks the user is authenticated until the next restart.

Modify the logOut method in Network:

Future<void> logOut(apiUrl) async { 
  var fullUrl = url + apiUrl; 
  SharedPreferences localStorage = await SharedPreferences.getInstance(); 
  await localStorage.remove('token'); 

  // Reset provider state to reflect logged-out status
  _authToken = '';
  _isAuth = false;
  token = null; // Clear the token used in API headers
  notifyListeners(); // Tell the UI to update

  // Optional: Only call the logout API if needed (some apps skip this if token is already invalid)
  try {
    await http.get(Uri.parse(fullUrl), headers: setHeaders());
  } catch (e) {
    // Handle API errors gracefully (e.g., token already expired)
    print('Logout API error: $e');
  }
}

3. Fix App Startup Authentication Check

Your main.dart is checking authToken != null directly, but authToken is a Future<String?>—it will never be null (it's a Future object, not the token value itself). Use a FutureBuilder to wait for the token check to complete.

Update the home property in MyApp:

home: FutureBuilder<String?>(
  future: Provider.of<Network>(context, listen: false).authToken,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator()); // Show loading while checking
    }
    // If token exists, go to home; else, go to login
    return snapshot.data != null ? const BottomNavigation() : const SignIn();
  },
),

4. Update Provider State on Login

After saving the token to local storage, update your provider's state so the UI reflects the authenticated status immediately.

Add this method to your Network class:

void setAuthenticated(String newToken) {
  _authToken = newToken;
  _isAuth = true;
  token = newToken;
  notifyListeners();
}

Call it in your _login method:

else { 
  SharedPreferences localStorage = await SharedPreferences.getInstance(); 
  String token = body['access_token'];
  localStorage.setString('token', token); 
  // Update provider state
  Provider.of<Network>(context, listen: false).setAuthenticated(token);
  Navigator.of(context).pushReplacementNamed('/bottom-bar'); 
}

5. Optimize API Headers

Avoid sending invalid Authorization headers when the token is null:

Map<String, String> setHeaders() {
  Map<String, String> headers = {
    'Content-type': 'application/json',
    'Accept': 'application/json',
  };
  if (token != null) {
    headers['Authorization'] = 'Bearer $token';
  }
  return headers;
}

6. Additional Best Practices

  • Use async/await consistently: Make sure all calls to SharedPreferences and APIs are properly awaited.
  • Handle loading states: Add loading indicators during login/logout to improve UX.
  • Clear all user data on logout: If you store other user info (like profile data), remove that from local storage too.
  • Add error handling: Wrap API calls in try/catch blocks to handle network errors gracefully.

After implementing these changes, your logout should properly clear the token, update the app state, and redirect to the login screen. Restarting the app after logout will now show the login screen instead of the home page, and the null check error should be gone.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 16:42:28