Flutter Hive 打开现有框,但未从中读取值



我有一个编程时刻,我觉得我快疯了,所以希望有人可以帮助我。

我有一个 Flutter 应用程序,它使用 Hive 在运行之间存储数据。 当应用最初启动时,它会打开一个框并检索一些信息,以便为 MaterialApp 设置保存的主题。 然后,它会为应用构建主页并检索一系列其他选项。 这运行良好(我的手机上有一个运行完美的版本),但由于某种原因它已停止工作。

当应用执行时,初始 MyApp 会声明 Hive 框已打开,但其中没有值。 对于调用选项类以检索选项数据,情况就是如此。 在那次调用之后,盒子突然有了值,我能够检索和打印出密钥。 当应用随后生成主页时,它会声明该框已打开,并且具有值,并且能够从选项类中检索选项数据。 以前,我在第一次读取数据以提取主题时没有问题。 我已经在下面发布了代码的相关部分,其中包含运行的打印输出。

我正在 Web 上运行该应用程序,并在移动模拟器上运行它。 它以前在两个平台上都运行良好,但现在无法在 Web 平台上工作。 它似乎在移动模拟器上运行良好。

该应用程序使用以下版本:

Flutter 2.10.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision c860cba910 (6 days ago) • 2022-03-25 00:23:12 -0500
Engine • revision 57d3bac3dd
Tools • Dart 2.16.2 • DevTools 2.9.2
pubspec.yaml dependencies:
hive: ^2.0.6
hive_flutter: ^1.1.0 

我今天已升级到最新版本的 Flutter,看看是否可以解决问题。 我在以前的稳定版本中遇到了同样的问题。

我已经更新到 hive 2.1.0 并获得相同的问题/输出。

我还尝试使用 Dart 2.10.0 将 Flutter 降级到 2.16.0,我知道它工作正常,但这并没有解决问题。

主飞镖

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:responsive_sizer/responsive_sizer.dart';
import 'package:lettercloud/data/colours.dart';
import 'package:lettercloud/options/option_page.dart';
const String _boxName = 'lettercloud';
void main() async {
await Hive.initFlutter();
Hive
..registerAdapter(CellAdapter())
..registerAdapter(ThemeModeOptionAdapter());
await Hive.openBox(_boxName);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
final Box _box = Hive.box(_boxName); // Object for hive data access
final Options _options = Options();
final Colours _colours = Colours();
late bool _firstRun = true; // Flag to only read Hive options on first run
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
print('build() Before first run.  Extracting box keys. Attempt 1...');
for (String key in _box.keys) {
print('box keys: $key');
}
if (_firstRun) {
print(
'First run.  Hive box is open: ${_box.isOpen}  Box has values: ${_box.isNotEmpty}');
_options.setHiveBox(_box); // Pass hive object and retrieve options
_firstRun = false;
}
print('');
print('build() After first run.  Extracting box keys. Attempt 2...');
for (String key in _box.keys) {
print('box keys: $key');
}
return AnimatedBuilder(
animation: _options.getThemeNotifier(),
builder: (context, child) {
return MaterialApp(
title: 'Lettercloud',
theme: FlexThemeData.light(scheme: FlexScheme.jungle),
darkTheme: FlexThemeData.dark(scheme: FlexScheme.jungle),
themeMode: _options.getThemeMode(),
home: ResponsiveSizer(
builder: (context, orientation, screenType) {
return const MyPage(title: 'Lettercloud Anagram Helper');
},
),
);
});
}
}
class MyPage extends StatefulWidget {
const MyPage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyPage> createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
final Options _options = Options();
late final Box _box; // Object for hive data access
late Widget _displayGrid;
@override
void initState() {
super.initState();
print('Doing init MyPageState');
_box = Hive.box(_boxName);
_options.setHiveBox(_box); // Pass hive object and retrieve options
_setGrid(_options.getGridType());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Lettercloud'),
),
resizeToAvoidBottomInset: false, // Overlay on-screen keyboard
body: SafeArea(
child: _displayGrid,
),
);
}
// Set the grid to display based on the grid type option
void _setGrid(GridType type) {
_displayGrid = _options.getGridType() == GridType.square
? GridSquare(box: _box, options: _options, update: updateGrid)
: GridDiamond(box: _box, options: _options, update: updateGrid);
}
// Callback to set the grid type if the option changes
void updateGrid(GridType type) {
setState(() {
_setGrid(type);
});
}
}

选项.dart

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:hive_flutter/hive_flutter.dart';
class Options {
bool _lightMode = true; // Use light colours, or dark
static const String _lightModeName = 'lightMode';
bool _showGrid = true; // Show grid around tiles, or not
static const String _showGridName = 'showGrid';
bool _firstEdit =
true; // Flag to show edit on first start, doesn't need saving
bool _editOnStart = false; // Show edit at startup, or not
static const String _editOnStartName = 'editOnStart';
CharType _charType = CharType.mixed; // Type of letters to show
static const String _charTypeName = 'charType';
ThemeModeOption _themeMode = ThemeModeOption()..setMode(ThemeMode.light);
static const String _themeModeName = 'themeMode';
late Box _box; // Hive object
late final double _tabletF; // Reduction factor for tablet displays
late GridType _gridType = GridType.square;
static const String _gridTypeName = 'gridType';
late GridType _savedGridType = _gridType;
static const String _savedGridTypeName = 'savedGridType';
// last page name - used to control text entry on startup
String _lastPage = PageName.main.toString();
static const String _lastPageName = 'lastPageName';
// Flag to show if the grid type has change.  Used to prevent 'show on start'
// triggering the text entry box after the grid layout has been changed by the user
bool _backFromOptionsPage = false;
final String _backFromOptionsPageName = 'fromOptions';
///
/// Hive management methods and global options setting
///
void setHiveBox(Box b) {
_box = b; // Pass the hive management object
print(
'Options hive box. Box is open: ${_box.isOpen}  Box has values: ${_box.isNotEmpty}.');
// Set screen size factor for web vs tablet
if (kIsWeb) {
_tabletF = 0.4; // Factor components by 0.4 for web
} else {
_tabletF = 0.6; // Factor components by 0.6 for tablets
}
// Retrieve any option data values
if (_box.get(_lightModeName) != null) {
_lightMode = _box.get(_lightModeName);
} else {
print('Cannot find $_lightModeName');
_box.put(_lightModeName, _lightMode);
}
if (_box.get(_showGridName) != null) {
_showGrid = _box.get(_showGridName);
} else {
_box.put(_showGridName, _showGrid);
}
if (_box.get(_editOnStartName) != null) {
_editOnStart = _box.get(_editOnStartName);
} else {
_box.put(_editOnStartName, _editOnStart);
}
if (_box.get(_charTypeName) != null) {
String temp = _box.get(_charTypeName);
_charType = getCharEnum(temp);
} else {
_box.put(_charTypeName, _charType.toString());
}
if (_box.get(_themeModeName) != null) {
_themeMode = _box.get(_themeModeName);
} else {
_box.put(_themeModeName, _themeMode);
}
if (_box.get(_gridTypeName) != null) {
String temp = _box.get(_gridTypeName);
_gridType = getGridEnum(temp);
} else {
_box.put(_gridTypeName, _gridType.toString());
}
if (_box.get(_savedGridTypeName) != null) {
String temp = _box.get(_savedGridTypeName);
_savedGridType = getGridEnum(temp);
} else {
_box.put(_savedGridTypeName, _savedGridType.toString());
}
if (_box.get(_backFromOptionsPageName) != null) {
_box.put(_backFromOptionsPageName, _backFromOptionsPage);
} else {
_box.put(_backFromOptionsPageName, _backFromOptionsPage);
}
// Load last page value or reset if doesn't exit
if (_box.get(_lastPageName) != null) {
_box.put(_lastPageName, _lastPage);
} else {
_box.put(_lastPageName, _lastPage);
}
_box.flush(); // Make sure everything is written to the disk
}
}

命令行输出:

flutter run -d chrome --web-renderer html --web-port 5555
Launching libmain.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             18.6s
This app is linked to the debug service: ws://127.0.0.1:54752/JAXqfQgauf4=/ws
Debug service listening on ws://127.0.0.1:54752/JAXqfQgauf4=/ws
Running with sound null safety
To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".
An Observatory debugger and profiler on Chrome is available at: http://127.0.0.1:54752/JAXqfQgauf4=
The Flutter DevTools debugger and profiler on Chrome is available at:
http://127.0.0.1:9101?uri=http://127.0.0.1:54752/JAXqfQgauf4=
build() Before first run.  Extracting box keys. Attempt 1...
First run.  Hive box is open: true  Box has values: false
Options hive box. Box is open: true  Box has values: false.
Cannot find lightMode
build() After first run.  Extracting box keys. Attempt 2...
box keys: charType
box keys: editOnStart
box keys: fromOptions
box keys: gridType
box keys: lastPageName
box keys: lightMode
box keys: savedGridType
box keys: showGrid
box keys: themeMode
Doing init MyPageState
Options hive box. Box is open: true  Box has values: true.
Application finished.

更新#1自最初发布以来,我尝试删除该框并重新运行该应用程序,以防这是由损坏的文件引起的。 这没有任何区别。

我还尝试在 openBox() 命令中添加一个 .then,以防这是另一个异步编程问题,但这也没有区别,即

await Hive.openBox(_boxName).then((value) {
print('value is $value');
runApp(MyApp());
});

更新 #2所以,我花了一段时间才解决这个问题,但如果它们尚不存在,我会在第一次运行时创建我的框值(以解决应用程序首次运行的用例)。 如果我删除 setHiveBox() 方法中的所有 put 语句,那么我就会一直遇到问题。 换句话说,在我的 Options 类在应用运行时创建这些值之前,框中没有值。 这表明应用程序未将数据保存到磁盘。 我已经将main.dart和options.dart与最近已知的工作版本进行了比较,没有看到任何明显的差异。 什么会阻止应用程序将数据保存到磁盘? 请注意,我已经测试了我开发的另一个使用 Hive 的应用程序,并且它继续完美运行。它使用与此应用程序相同的Hive版本。

我通过在项目上执行flutter clean,删除颤振安装(从磁盘中完全删除安装文件夹),下载并重新安装Flutter,然后在项目文件夹上执行flutter pub get来解决此问题。

我之前尝试过flutter clean并自行flutter pub get,但这并没有解决问题,所以上次升级后 flutter 文件夹本身出了问题? 无论如何,所有内容的全新安装都解决了问题。

相关内容

  • 没有找到相关文章

最新更新