Flutter+Hive在FutureBuilder中判断Box值提示未打开Box如何解决
问题根因
- 你在
build方法的起始位置就执行了final user = Hive.box('user'),这时候FutureBuilder的Hive.openBox('user')异步操作还未完成,box还没有被初始化,所以直接调用Hive.box()就会抛出找不到box的错误。 - 异步操作完成后你又重复调用了一次
Hive.openBox('user'),属于多余操作,FutureBuilder的future参数已经帮你完成了打开box的操作。 - 另外你的
MyApp类的createState返回类型写错了,你定义的State是_PocketPolarixState,但是StatefulWidget是MyApp,这里会有类型错误。
修正后的完整代码
import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import 'package:myapp/model/user_model.dart'; import 'package:myapp/views/login_view.dart'; import 'package:myapp/views/project_view.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); final appDocsDir = await path_provider.getApplicationDocumentsDirectory(); Hive.init(appDocsDir.path); Hive.registerAdapter(UserModelAdapter()); runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); // 修正返回的State类型 @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { return MaterialApp( title: 'Startup Name Generator', theme: ThemeData( appBarTheme: const AppBarTheme( backgroundColor: Color(0xFF2036B8), foregroundColor: Colors.white, ), ), home: FutureBuilder( future: Hive.openBox('user'), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.hasError) { return Scaffold( body: Center(child: Text(snapshot.error.toString())), ); } else { // 打开完成后再获取box,此时box已经初始化完成 final userBox = Hive.box('user'); if (userBox.get('token') != null) { return const ProjectView(); } else { return const LoginView(); } } } else { // 加载过程中显示加载指示器,避免空白页 return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } }, ), ); } @override void dispose() { Hive.close(); super.dispose(); } }
额外优化建议
你也可以直接在main方法里提前打开user box,就不用在页面里加FutureBuilder了,逻辑更简洁:
void main() async { WidgetsFlutterBinding.ensureInitialized(); final appDocsDir = await path_provider.getApplicationDocumentsDirectory(); Hive.init(appDocsDir.path); Hive.registerAdapter(UserModelAdapter()); // 提前打开box await Hive.openBox('user'); runApp(const MyApp()); }
之后在MyApp的build方法里就可以直接判断token,不需要FutureBuilder包裹。
内容的提问来源于stack exchange,提问作者Justin Erswell
相关产品推荐
相关产品推荐

