2

我正在尝试使用Hive内部颤振Mobx,在检查用户数据后,Hive我切换到另一个屏幕,例如HomeViewIntro

main.dart

Future<void> main() async {
  ...

  final appDocumentDirectory = await path_provider.getApplicationDocumentsDirectory();
  Hive.init(appDocumentDirectory.path);
  Hive.registerAdapter(UserAdapter());

  _setUpLogging();

  runApp(MultiProvider(providers: providers, child: StartupApplication()));
}

StartupApplication班级:我不使用Hive

class StartupApplication extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final isPlatformDark = WidgetsBinding.instance.window.platformBrightness == Brightness.dark;
    final initTheme = isPlatformDark ? nebrassLightTheme : nebrassLightTheme;
    return ThemeProvider(
      initTheme: initTheme,
      duration: const Duration(milliseconds: 400),
      child: Builder(builder: (context) {
        return MaterialApp(
          title: 'TEST',
          theme: ThemeProvider.of(context),
          home: const OverlaySupport(child: OKToast(
           child: MyHomePage() //--> checking user data widget
          )),
          onGenerateRoute: Routes.sailor.generator(),
          navigatorKey: Routes.sailor.navigatorKey,
        );
      }),
    );
  }
}

签到UserHiveMyHomePage

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<Box<User>>(
            future: Hive.openBox('user'),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                final Box<User> userBox = snapshot.data;
    
                if (userBox.values.isNotEmpty && userBox.get(0).active == 1) {
                  return HomeView();
                } else {
                  return Intro();
                }
              } else {
                return Container();
              }
            });
      }
    
      @override
      void dispose() {
        Hive.close();
        super.dispose();
      }
    }

现在在其他屏幕中,例如RegisterScreen我实现的类MobX和我想在其中使用user的框,例如:

class Register extends StatefulWidget {
  @override
  _RegisterState createState() => _RegisterState();
}

class _RegisterState extends State<Register> {
  TextEditingController _mobileNumber;

  final GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();
    _mobileNumber = TextEditingController();
  }

  @override
  Widget build(BuildContext context) {
    final _registerViewModel = Provider.of<RegisterViewModel>(context, listen: false);

    return Directionality(
      textDirection: TextDirection.ltr,
      child: Scaffold(
        key: _scaffoldState,

        ...
        //_registerViewModel.registerAccount(_mobileNumber.text, '111');

      ),
    );
  }

  void _showSnackBar(String message, BuildContext context) {
    _scaffoldState.currentState.showSnackBar(SnackBar(
        content: Directionality(
            textDirection: TextDirection.rtl,
            child: Text(
              '$message',
              style: AppTheme.of(context).caption().copyWith(color: Colors.white),
            ))));
  }
}

MobX执行:

enum RegisterLoadingState { loading, done }
enum ActiveLoadingState { loading, done }
enum RegisteringState { initial, registered, activated, registerError, activeError }

class RegisterViewModel = _RegisterViewModel with _$RegisterViewModel;

abstract class _RegisterViewModel with Store {
  final WebApi _webApi;

  _RegisterViewModel({@required WebApi webApi}) : _webApi = webApi;

  ...

  @action
  Future<void> registerAccount(String mobileNumber, String deviceId) async {
    final RegisterRequest _request = RegisterRequest(mobileNumber, deviceId);
    try {
      loadingState = RegisterLoadingState.loading;
      final _res = await _webApi.register(_request);
      loadingState = RegisterLoadingState.done;

      _registerResponse = RegisterResponse.fromJson(_res.body as Map<String, dynamic>);

      /* I GET ERROR IN THIS LINE -- HiveError: The box "user" is already open and of type Box<User>.*/

      final userBox = await Hive.openBox('user');
      final user = User(/*...*/);
      userBox.putAt(0, user);
  }

  @action
  Future<void> activeAccount(String mobileNumber, String verifyCode) async {
    final ActiveAccountRequest _activeAccount = ActiveAccountRequest(mobileNumber, verifyCode);

    final userBox = await Hive.openBox('user');
    final User currentUser = userBox.getAt(0) as User;
    final user = User(/*...*/);
    userBox.putAt(0, user);
  }
}
4

3 回答 3

4
  1. 您可以在应用程序的方法中打开您的userBox main
Future<void> main() async {
  ...

  final appDocumentDirectory = await path_provider.getApplicationDocumentsDirectory();
  Hive.init(appDocumentDirectory.path);
  Hive.registerAdapter(UserAdapter());
  // open the user box
  await Hive.openBox('user');

  _setUpLogging();

  runApp(MultiProvider(providers: providers, child: StartupApplication()));
}
  1. 访问先前打开的框,如下所示:
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // user box
  Box userBox;

  @override
  void initState() {
    super.initState();
    // get the previously opened user box
    userBox = Hive.box('user');
  }

  @override
  Widget build(BuildContext context) {
    // check for your conditions 
    return (userBox.values.isNotEmpty && userBox.get(0).active == 1)
        ? HomeView()
        : Intro();
  }
}
于 2020-08-30T19:03:04.237 回答
4

我已经给 Hive 第一次尝试并观察了这一点。

如果你像这样打开盒子:

await Hive.openBox("MyModelBox");

它会抛出异常:

Box not found. Did you forget to call Hive.openBox()?

让我们看一下Box

BoxBase<E> _getBoxInternal<E>(String name, [bool? lazy]) {
    var lowerCaseName = name.toLowerCase();
    var box = _boxes[lowerCaseName];
    if (box != null) {
      if ((lazy == null || box.lazy == lazy) && box.valueType == E) {
        return box as BoxBase<E>;
      } else {
        var typeName = box is LazyBox
            ? 'LazyBox<${box.valueType}>'
            : 'Box<${box.valueType}>';
        throw HiveError('The box "$lowerCaseName" is already open '
            'and of type $typeName.');
      }
    } else {
      throw HiveError('Box not found. Did you forget to call Hive.openBox()?');
    }
  }

box.valueTypedynamicE将是您的类模型类型MyModel。因此他们不会平等。

但是如果你传递特定类型的模型

await Hive.openBox<MyModel>("MyModelBox");

错误消失。

于 2021-06-02T13:38:44.180 回答
1

发生这种情况是因为您已经在某处以相同名称定义了另一个类型为 User 的框(使用

final myBoxName = 'userBox';
Hive.openBox<User>(myBoxName);

并尝试用另一种类型打开同名的盒子,例如

Hive.openBox<bool>(myBoxName);

因此,flutter 在打开盒子时当然会遇到问题,因为它已经与另一种类型一起存在。

您必须找到使用不同类型的位置并通过使用不同的名称来解决问题。

于 2021-08-20T15:09:30.067 回答