Flutter应用登出时Token未清除及空值异常问题咨询
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/awaitconsistently: 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

