Flutter Secure Storage读取时报Null check operator空值错误如何解决
问题成因
- 核心原因是所有Flutter原生交互插件(包括flutter_secure_storage)都依赖Flutter框架的平台通道绑定,你在调用存储读写操作前没有执行
WidgetsFlutterBinding.ensureInitialized()初始化绑定,导致底层MethodChannel的binaryMessenger为空,抛出空校验错误。 - 次要问题是你调用异步函数
tryAssignAccessId()时没有加await,导致存储初始化和检查操作还没完成,后续的读操作就已经执行,也可能触发异常。 - 此前你把初始化放在runApp之后时,FutureBuilder的异步任务会先执行,此时FAS还没初始化,同样会触发空错误。
解决方案
按照以下步骤修改代码即可解决:
- 将main函数改为异步函数,第一行先执行
WidgetsFlutterBinding.ensureInitialized()完成框架绑定初始化 - 调用
FAS.init()完成存储类初始化 - 给
tryAssignAccessId()加上await,等待accessId检查赋值完成后再执行runApp - 可选优化:给FutureBuilder的data返回值加空保护,避免异常场景下的空校验错误
修改后的main.dart代码
import 'package:flutter/material.dart'; import 'package:unified_bot_app/pages/home_page.dart'; import 'package:uuid/uuid.dart'; import './models/fas.dart'; import './pages/sign_in_page.dart'; import './request_methods.dart'; Future<void> tryAssignAccessId() async { String? accessId = await FAS.read("ACCESS_ID"); if (accessId == null) { await FAS.write("ACCESS_ID", (const Uuid()).v4()); } } // 改为异步main函数 void main() async { // 必须先初始化Flutter框架绑定 WidgetsFlutterBinding.ensureInitialized(); FAS.init(); // 等待accessId检查完成 await tryAssignAccessId(); runApp( MaterialApp( home: FutureBuilder<bool>( builder: (ctx, a) { if (a.connectionState == ConnectionState.done) { // 加空保护,避免data为空时报错 if (a.data ?? false) return HomePage(); return const SignInPage(); } return const Center(child: CircularProgressIndicator()); }, future: () async { try { String? accessKey = await FAS.read("ACCESS_KEY"); if (accessKey == null) { return false; } return await HTTP.authenticate(accessKey); } catch (e) { print(e); return false; } }(), ), theme: ThemeData(fontFamily: "Josefin Sans"), ), ); }
可选FAS类优化(增加初始化校验)
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; class FAS { static FlutterSecureStorage? _storage; static void init() { _storage = const FlutterSecureStorage( aOptions: AndroidOptions(encryptedSharedPreferences: true), ); } static Future<String?> read(String key) async { // 开发阶段提前发现未初始化的问题 assert(_storage != null, '请先调用FAS.init()完成初始化'); return _storage?.read(key: key); } // 其余方法同理增加判空/断言校验 static Future<Map<String, String>> readAll() async { assert(_storage != null, '请先调用FAS.init()完成初始化'); return _storage?.readAll() ?? {}; } static Future<void> write(String key, String value) async { assert(_storage != null, '请先调用FAS.init()完成初始化'); await _storage?.write(key: key, value: value); } static Future<void> delete(String key) async { assert(_storage != null, '请先调用FAS.init()完成初始化'); await _storage?.delete(key: key); } static Future<void> deleteAll() async { assert(_storage != null, '请先调用FAS.init()完成初始化'); await _storage?.deleteAll(); } }
内容的提问来源于stack exchange,提问作者Saumitra Topinkatti
相关产品推荐
相关产品推荐

