Flutter Secure Storage 错误 Null check operator used on a null value

Flutter Secure Storage error Null check operator used on a null value

我正在尝试制作一个包含登录屏幕和主屏幕(目前只有两个屏幕)的 Flutter 应用程序。我也在使用 Flutter Secure Storage 和 Http 库。

每当应用程序启动时,我希望应用程序检查两个道具 accessKey 和 accessId 是否存储在安全存储中。如果找不到 accessId,它会自动生成并分配给 Uuid 库。而 accessKey 不是本地生成的,而是由 API.

提供的

应用导航到:
1). HomeScreen,如果accessKey存储在Secure Storage中并且认证成功。
2). SignInScreen,如果没有找到accessKey或者验证失败。

我的问题是,每次我执行读取操作时,Secure Storage 都会不断抛出错误“Null 检查运算符用于空值”手术。我已经初始化了存储变量,但是这个问题一直出现。

这是我的安全存储 class 代码:

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 {
    return _storage!.read(key: key);
  }

  static Future<Map<String, String>> readAll() async {
    return _storage!.readAll();
  }

  static Future<void> write(String key, String value) async {
    await _storage!.write(key: key, value: value);
  }

  static Future<void> delete(String key) async {
    await _storage!.delete(key: key);
  }

  static Future<void> deleteAll() async {
    await _storage!.deleteAll();
  }
}

之前,该代码的部分是这样的:

static const FlutterSecureStorage _storage = FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true));

没有初始化方法。

但我一直收到同样的错误。

这是我的 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());
  }
}

void main() {
  FAS.init();
  tryAssignAccessId(); // <- Error  

  runApp(
    MaterialApp(
      home: FutureBuilder<bool>(
        builder: (ctx, a) {
          if (a.connectionState == ConnectionState.done) {
            if (a.data!) 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) {
            return false;
          }
        }(),
      ),
      theme: ThemeData(fontFamily: "Josefin Sans"),
    ),
  );
}  

这是我重新启动应用程序时得到的输出:

Restarted application in 531ms. E/flutter (20760):
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Null
check operator used on a null value E/flutter (20760): #0
MethodChannel.binaryMessenger
package:flutter/…/services/platform_channel.dart:121 E/flutter
(20760): #1 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:146 E/flutter
(20760): #2 MethodChannel.invokeMethod
package:flutter/…/services/platform_channel.dart:329 E/flutter
(20760): #3 MethodChannelFlutterSecureStorage.read
package:flutter_secure_storage_platform_interface/src/method_channel_flutter_secure_storage.dart:49
E/flutter (20760): #4 FlutterSecureStorage.read
package:flutter_secure_storage/flutter_secure_storage.dart:91
E/flutter (20760): #5 FAS.read
package:unified_bot_app/models/fas.dart:13 E/flutter (20760): #6
tryAssignAccessId package:unified_bot_app/main.dart:10 E/flutter
(20760): #7 main package:unified_bot_app/main.dart:18 E/flutter
(20760): #8 _runMainZoned..
(dart:ui/hooks.dart:145:25) E/flutter (20760): #9 _rootRun
(dart:async/zone.dart:1428:13) E/flutter (20760): #10
_CustomZone.run (dart:async/zone.dart:1328:19) E/flutter (20760): #11 _runZoned (dart:async/zone.dart:1863:10) E/flutter (20760): #12 runZonedGuarded (dart:async/zone.dart:1851:12) E/flutter (20760): #13
_runMainZoned. (dart:ui/hooks.dart:141:5) E/flutter (20760): #14 _delayEntrypointInvocation.
(dart:isolate-patch/isolate_patch.dart:283:19) E/flutter (20760): #15
_RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12) E/flutter (20760):
D/EGL_emulation(20760): app_time_stats: avg=14143.50ms min=14143.50ms
max=14143.50ms count=1

但是,当我将前两行放在最后(在 runApp(..) 之后)时,错误消失了:

void main() {
  runApp(
    MaterialApp(
      home: FutureBuilder<bool>(
        builder: (ctx, a) {
          if (a.connectionState == ConnectionState.done) {
            if (a.data!) return HomePage();
            return const SignInPage();
          }

          return const Center(child: CircularProgressIndicator());
        },
        future: () async {
          try {
            String? accessKey = await FAS.read("ACCESS_KEY"); // <- Error re-appears here  
            if (accessKey == null) {
              return false;
            }

            return await HTTP.authenticate(accessKey);
          } catch (e) {
            return false;
          }
        }(),
      ),
      theme: ThemeData(fontFamily: "Josefin Sans"),
    ),
  );

  FAS.init();
  tryAssignAccessId();
}  

但是这样做,错误会再次出现在标记的行上。

我很困惑。发生了什么? 感谢任何帮助。

编辑 1:
我尝试在调用第二个 read() 方法之前调用 init() 方法,但抛出相同的错误。

更新部分:

future: () async {
          try {
            FAS.init();
            String? accessKey = await FAS.read("ACCESS_KEY");
            if (accessKey == null) {
              return false;
            }

            return await HTTP.authenticate(accessKey);
          } catch (e) {
            print(e);
            return false;
          }
        }(),  

控制台输出:

Restarted application in 510ms. I/flutter (20760): Null check operator
used on a null value D/EGL_emulation(20760): app_time_stats:
avg=1899.03ms min=1899.03ms max=1899.03ms count=1

我通过添加包含所有方法的新空白页解决了这个问题。

空白页文件:

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

import '../models/fas.dart';
import '../request_methods.dart';
import './home_page.dart';
import './sign_in_page.dart';

class BlankPage extends StatelessWidget {
  Future<void> _tryAssignAccessId() async {
    String? accessId = await FAS.read("ACCESS_ID");
    if (accessId == null) {
      await FAS.write("ACCESS_ID", (const Uuid()).v4());
    }
  }

  Future<bool> _checkAuth() async {
    try {
      String? accessKey = await FAS.read("ACCESS_KEY");
      if (accessKey == null) {
        return false;
      }

      return await HTTP.authenticate(accessKey);
    } catch (e) {
      return false;
    }
  }

  @override
  Widget build(BuildContext context) {
    FAS.init();
    _tryAssignAccessId();
    _checkAuth().then((result) {
      if (result) {
        Navigator.of(context)
            .pushReplacement(MaterialPageRoute(builder: (ctx) => HomePage()));
      } else {
        Navigator.of(context).pushReplacement(
            MaterialPageRoute(builder: (ctx) => const SignInPage()));
      }
    });

    return Scaffold();
  }
}  

已更新 main.dart(供参考):

import 'package:flutter/material.dart';

import './pages/blank.dart';

void main() {
  runApp(
    MaterialApp(
      home: BlankPage(),
      theme: ThemeData(fontFamily: "Josefin Sans"),
    ),
  );
}

我通过添加

解决了这个问题
WidgetsFlutterBinding.ensureInitialized();

到 runApp() 之前的 main() 方法。