0

I'm trying to fetch some values from Hive to check whether data is available or I need to fetch it again. I'm using hive to save the data. I'm using Layout builder in main.dart with a navigator widget to set up named routes.

My Initial route is the project_list.dart. And this is the code inside project_list.dart :

class ProjectsList extends StatefulWidget {
  const ProjectsList({Key? key}) : super(key: key);
  static const String id = 'ProjectsList';

  @override
  State<ProjectsList> createState() => _ProjectsListState();
}

class _ProjectsListState extends State<ProjectsList> {

  late Box<LoggedInUser> userBox;
  late Box<List<ProjectModal>> projectBox;

  List<ProjectModal> projectList = [];
  List<ProjectModal> projectListFiltered = [];

  GlobalKey<RefreshIndicatorState> _indicatorKey = GlobalKey<RefreshIndicatorState>();

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

  bool isLoading = false;
  bool isSearching = false;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getHiveBox();
  }

  Future<void> getHiveBox() async {
    userBox = Hive.box(LoggedInUser.boxID);
    projectBox = Hive.box<List<ProjectModal>>(ProjectModal.boxID);


    // HERE IS THE PROBLEM
    // It crashes on projectBox.values

    print(projectBox.values.first.length);

    if (projectBox.values.first.isEmpty) {
      print('EMPTY PROJECT LIST');
      await getProjectsList();
    }

  }

  Future<void> getProjectsList() async {
    // _indicatorKey.currentState?.show();
    SchedulerBinding.instance?.addPostFrameCallback((_){  
_indicatorKey.currentState?.show(); } );
    WebServices webServices = WebServices(URLs.projectList());
    var data = await webServices.get(isV1: false);
    var projectListData = ProjectModal.getProjectsList(data);
    setState(() {
      isLoading = false;
      projectList = projectListData;
    });
  }

It crashes on projectBox.values and it fixes when I remove that code. I need to save that data offline, and I read Hive was the fastest way to store data offline in flutter. Furthermore, I'm new to dart, so I don't know if Hive is the reason for this or not. It sure has given me a lot of errors. Here is the error stack displayed in the console

[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: Bad state: No element
#0      Iterable.first (dart:core/iterable.dart:490:7)
#1      MappedIterable.first (dart:_internal/iterable.dart:370:31)
#2      _ProjectsListState.getHiveBox         
(package:thareja_time_tracker/views/projects_list.dart:48:29)
#3      _ProjectsListState.initState.<anonymous closure>     
(package:thareja_time_tracker/views/projects_list.dart:40:7)
#4      new Future.delayed.<anonymous closure> (dart:async/future.dart:315:39)
#5      _rootRun (dart:async/zone.dart:1420:47)
#6      _CustomZone.run (dart:async/zone.dart:1328:19)
#7      _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#8      _CustomZone.bindCallbackGuarded.<anonymous closure>     
(dart:async/zone.dart:1276:23)
#9      _rootRun (dart:async/zone.dart:1428:13)
#10     _CustomZone.run (dart:async/zone.dart:1328:19)
#11     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1260:23)
#12     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.<…>

EDIT: I saw that when trying to access an empty iterable, this error popped up, so I changed it to this :

Future<void> getHiveBox() async {
    userBox = Hive.box<LoggedInUser>(LoggedInUser.boxID);
    projectBox = Hive.box<List<ProjectModal>>(ProjectModal.boxID);

    print(projectBox.values.length);

    List<ProjectModal> first = projectBox.values.isEmpty ? [] : projectBox.values.first;

    print(first.length);

    if (first.isEmpty) {
        print('EMPTY PROJECT LIST');
        await getProjectsList();
    } else {
        print('PROJECT LIST DETECTED\n${first.length}');
        setState(() {
          projectList = first;
        });
    }
  }

But now, the error has changed to Unhandled Exception: type 'List' is not a subtype of type 'List' in type cast

Specifically in the .first part of projectBox.values.first I can print projectBox.values, which is always 1 (one list), but can't even print projectBox.values.first

leftjoin
  • 36,950
  • 8
  • 57
  • 116
araina1995
  • 21
  • 1
  • 3

1 Answers1

0

You can not call first on an empty Iterable:

List<ProjectModal> first = projectBox.values.isEmpty ? [] : projectBox.values.first.cast<ProjectModal>();
print(first.length);
if(first.isEmpty){
    print('EMPTY PROJECT LIST');
    await getProjectsList();
}
Mäddin
  • 1,070
  • 6
  • 11
  • Hi, I tried this too, but I get another exception that says Unhandled Exception: type 'List' is not a subtype of type 'List' in typecast and its on projectBox.values.first, specifically the .first – araina1995 Sep 24 '21 at 11:57
  • I updated my answer, but this exception indicates that your `HiveBox` hast not of the correct type. – Mäddin Sep 26 '21 at 11:17