Search code examples
flutterdartgoogle-cloud-firestoredart-null-safety

dart/flutter:: type 'Null' is not a subtype of type 'String' in type cast ERRor, not able to fetch data


I am running into a "type 'Null' is not a subtype of type 'String' in type cast" when I try to retrieve the data.

not sure what the issue is... I think the data is not being found or something along those lines

source code:: https://github.com/casas1010/flutter_firebase_vendor_management

error message::

════════ Exception caught by widgets library ═══════════════════════════════════
The following _CastError was thrown building JobApplicationsListView(dirty):
type 'Null' is not a subtype of type 'String' in type cast

The relevant error-causing widget was
JobApplicationsListView
lib/…/job_applications/job_application_view.dart:75
When the exception was thrown, this was the stack
#0      new CloudJobApplication.fromSnapshot
package:ijob_clone_app/…/cloud/cloud_job_application.dart:27
#1      FirebaseCloudStorage.allJobApplications.<anonymous closure>.<anonymous closure>
package:ijob_clone_app/…/cloud/firebase_cloud_storage.dart:49
#2      MappedListIterable.elementAt (dart:_internal/iterable.dart:413:31)
#3      ListIterator.moveNext (dart:_internal/iterable.dart:342:26)
#4      WhereIterator.moveNext (dart:_internal/iterable.dart:438:22)
#5      Iterable.length (dart:core/iterable.dart:497:15)
#6      JobApplicationsListView.build
package:ijob_clone_app/…/widgets/job_application_list_widget.dart:27
#7      StatelessElement.build
package:flutter/…/widgets/framework.dart:4949
#8      ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4878
#9      Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#10     ComponentElement._firstBuild
package:flutter/…/widgets/framework.dart:4859
#11     ComponentElement.mount
package:flutter/…/widgets/framework.dart:4853
#12     Element.inflateWidget
package:flutter/…/widgets/framework.dart:3863
#13     Element.updateChild
package:flutter/…/widgets/framework.dart:3586
#14     ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#15     StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#16     Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#17     BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2667
#18     WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:882
#19     RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:378
#20     SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1175
#21     SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1104
#22     SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:1015
#23     _invoke (dart:ui/hooks.dart:148:13)
#24     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#25     _drawFrame (dart:ui/hooks.dart:115:31)
════════════════════════════════════════════════════════════════════════════════
D/TrafficStats( 9769): tagSocket(99) with statsTag=0xffffffff, statsUid=-1

CloudJobApplication::

@immutable
class CloudJobApplication {
  final String documentId;
  final String jobApplicatorId;
  final String jobApplicationState;
  final String jobApplicationSubState;

  const CloudJobApplication({
    required this.documentId,
    required this.jobApplicatorId,
    required this.jobApplicationState,
    required this.jobApplicationSubState,
  });

  // acts as constructor
  CloudJobApplication.fromSnapshot(
      QueryDocumentSnapshot<Map<String, dynamic>> snapshot)
      : documentId = snapshot.id,
        jobApplicatorId = snapshot.data()[jobApplicatorIdColumn] as String,
        jobApplicationState =
            snapshot.data()[jobApplicationStateColumn] as String,
        jobApplicationSubState =
            snapshot.data()[jobApplicationSubStateColumn] as String;
}

FirebaseCloudStorage::


class FirebaseCloudStorage {
  final job = FirebaseFirestore.instance.collection('jobs');
  final jobApplication =
      FirebaseFirestore.instance.collection('job applications');

// This works perfect for getting the jobs
  Stream<Iterable<CloudJob>> allJobs({required String jobCreatorId}) =>
      job.snapshots().map((event) => event.docs
          .map((doc) => CloudJob.fromSnapshot(doc))
          .where((job) => job.jobCreatorId == jobCreatorId));


// this does not work. i copied the code from above and changed it 
  Stream<Iterable<CloudJobApplication>> allJobApplications() =>
      jobApplication.snapshots().map((event) => event.docs
          .map((doc) => CloudJobApplication.fromSnapshot(doc))
          .where((jobApplication) =>
              jobApplication.documentId == 'f2FvzZmr51v1wyrYZYoM'));

 
// singleton
  static final FirebaseCloudStorage _shared =
      FirebaseCloudStorage._sharedInstance();
  FirebaseCloudStorage._sharedInstance();
  factory FirebaseCloudStorage() => _shared;
}

JobApplicationsView:: ( this is where the issue starts, the issue appears when this widget tries to retrieve the data from the server i thin )

import 'package:flutter/material.dart';
import '../../services/cloud/cloud_job_application.dart';
import '../../utilities/widgets/job_application_list_widget.dart';
import '../../utilities/widgets/jobs_list_widget.dart';
import '/constants/routes.dart';
import '/enums/menu_action.dart';
import '/services/auth/auth_service.dart';
import '/services/cloud/cloud_job.dart';
import '/services/cloud/firebase_cloud_storage.dart';
import '/utilities/dialogs/logout_dialog.dart';

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

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

class _JobApplicationsViewState extends State<JobApplicationsView> {
  late final FirebaseCloudStorage _jobsService;
  String get userId => AuthService.firebase().currentUser!.id;

  @override
  void initState() {
    _jobsService = FirebaseCloudStorage();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Your job applications'),
        actions: [
          IconButton(
            onPressed: () {
              // Navigator.of(context).pushNamed(createOrUpdateJobRoute);
            },
            icon: const Icon(Icons.add),
          ),
          PopupMenuButton<MenuAction>(
            onSelected: (value) async {
              prin('code removed')
            },
            itemBuilder: (context) {
              return const [
                PopupMenuItem<MenuAction>(
                  value: MenuAction.logout,
                  child: Text('Log out'),
                ),
              ];
            },
          )
        ],
      ),
      body: StreamBuilder(
        stream: _jobsService.allJobApplications(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
            case ConnectionState.active:
              if (snapshot.hasData) {
                final allJobs =  snapshot.data as Iterable<CloudJobApplication>;
                print(snapshot);
                return JobApplicationsListView(   // ERROR IS OCURRING HERE
                  jobs: allJobs,
                );
                return Text('results');
              } else {
                return const CircularProgressIndicator();
              }
            default:
              return const CircularProgressIndicator();
          }
        },
      ),
    );
  }
}

Job application firebase Job firebase ERROR, line 75


Solution

  • Try like this

      CloudJobApplication.fromSnapshot(
          QueryDocumentSnapshot<Map<String, dynamic>> snapshot)
          : documentId = snapshot.id,
            jobApplicatorId = snapshot.data()[jobApplicatorIdColumn] ?? "",
            jobApplicationState = snapshot.get(jobApplicationStateColumn) ?? "",
            jobApplicationSubState =
                snapshot.get(jobApplicationSubStateColumn) ?? "";