skip to Main Content

I am building an app to display data of medical providers store in Firebase realtime database. I use Getx for state management. I have a listview to display all of the available categories. when I click on the categories I pass a string which is a node in the database. but I keep getting Null check operator used on a null value despite making sure that I am passing the correct value.

Here is my MedicalProviderController class

  class MedicalProviderController extends GetxController {
      String? medicalProviderType;
    
      late DatabaseReference _medicalProviderRef;
    
      var medProvidersList = <MedicalProvider>[].obs;
    
      var filteredList = <MedicalProvider>[].obs;
    
      var selectedCity = 'city'.obs;
      var selectedSpecialty = 'specialty'.obs;
      var searchQuery = ''.obs;
      var isLoading = false.obs;
    
      MedicalProviderController();
    
      MedicalProviderController.withType({required this.medicalProviderType})
          : super();
    
      @override
      void onInit() {
        super.onInit();
        getProvidersData();
      }
    
      void getProvidersData() {
        isLoading.value = true;
    
        _medicalProviderRef = FirebaseDatabase.instance
            .ref()
            .child('medical_provider')
            .child(medicalProviderType!);
    
        _medicalProviderRef.onValue.listen((event) {
          final providerData = event.snapshot.value as Map<dynamic, dynamic>;
          medProvidersList.clear();
    
          providerData.forEach((key, value) {
            final medProvider = MedicalProvider(
                key: key,
                nameKu: value['nameKu'],
                specialization: value['specialization'],
                phone: value['phone'],
                city: value['city'],
                imageUrl: value['imageUrl'],
                isFeatured: value['isFeatured']);
    
            medProvidersList.add(medProvider);
          });
    
          filteredProviders();
          isLoading.value = false;
        });
      }
    
      void filteredProviders() {
        filteredList.assignAll(medProvidersList);
    
        if (selectedCity.value != 'city') {
          filteredList.removeWhere((element) =>
              element.city.toLowerCase() != selectedCity.value.toLowerCase());
        }
    
        if (searchQuery.value.isNotEmpty) {
          filteredList.removeWhere((element) => !element.nameKu
              .toLowerCase()
              .contains(searchQuery.value.toLowerCase()));
        }
      }
    
      void onSelectedCityChanged(String value) {
        selectedCity.value = value;
        filteredProviders();
      }
    
      void onSearchQueryChanged(String value) {
        searchQuery.value = value;
        filteredProviders();
      }
}

and here my screen to display the data

class MedProviderScreen extends StatelessWidget {


 final String medProviderType;

  const MedProviderScreen({Key? key, required this.medProviderType})
      : super(key: key);



@override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;

final medProviderController = Get.put(MedicalProviderController.withType(
    medicalProviderType: medProviderType));

return Scaffold(
  body: SafeArea(
    child: Column(
      children: [
        Container(
          height: size.height * 0.3,
          color: AppTheme.primaryColor,
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextFormField(
                    decoration: InputDecoration(
                        filled: true,
                        fillColor: AppTheme.whiteColor,
                        hintText: 'search'.tr,
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(8))),
                    onChanged: (value) {
                      medProviderController.onSearchQueryChanged(value);
                      medProviderController.filteredProviders();
                    }),
                const SizedBox(height: 8),
                citiesDropDownMenu(
                    value: medProviderController.selectedCity.value,
                    onChangeFun: (value) {
                      medProviderController.onSelectedCityChanged(value);
                      medProviderController.filteredProviders();
                    })
              ],
            ),
          ),
        ),
        Expanded(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Obx(() {
              final filteredData = medProviderController.filteredList;
              if (medProviderController.isLoading.value) {
                return const CircularProgressIndicator();
              } else if (filteredData.isEmpty) {
                return const Text('empty');
              } else {
                return ListView.builder(
                    itemCount: filteredData.length,
                    itemBuilder: (context, index) {
                      final medProvider = filteredData[index];

                      return SizedBox(
                        height: 75,
                        child: ListTile(
                          leading: CircleAvatar(
                            foregroundImage:
                                NetworkImage(medProvider.imageUrl),
                          ),
                          title: Text(medProvider.nameKu),
                          trailing: Text(medProvider.city),
                        ),
                      );
                    });
              }
            }),
          ),
        )
      ],
    ),
  ),
);

}
}
and here is code of when I click the listview items

child: InkWell(
                              splashColor: AppTheme.lightGreen,
                              onTap: () {
                                //  handleCategoriesNavigation(index, context);

                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) =>
                                             const MedProviderScreen(
                                              medProviderType: 'doctor',
                                            )));
                              },
                            ),

I get the error in my home screen and not when I click to navigate to the other screen.
It is worth mentioning that I have created this functionality once before but I had only one constructor in my controller class. this time I have 2 constructors.

update
what is causing the problem is controller class is being initialized in the home screen with default constructor that has no String parameter, I don’t understand why this is happening even though I have 2 constructors.

2

Answers


  1. The issue you’re facing seems to be related to passing the medicalProviderType value to the MedicalProviderController in your MedProviderScreen class. In your onTap method, you’re passing a hardcoded value of ‘doctor’ instead of the actual value you intend to pass.

    To fix this issue, you need to modify your onTap method to pass the correct value. Since you mentioned that you’re passing a string when clicking on the categories, you should have a way to retrieve that value and pass it to the MedProviderScreen. Here’s an example assuming you have a category variable representing the selected category:

    onTap: () {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => MedProviderScreen(
            medProviderType: category, // Pass the selected category here
          ),
        ),
      );
    },
    

    Make sure to replace category with the actual variable representing the selected category.

    Additionally, since you have two constructors in your MedicalProviderController class, you need to make sure you’re using the correct one when initializing the controller. In your MedProviderScreen class, you’re using the MedicalProviderController.withType() constructor, which requires the medicalProviderType parameter. Ensure that you’re passing the value correctly when creating the controller instance.

    If you’re still facing the issue after applying these changes, please provide the error message and stack trace to help further diagnose the problem.

    Login or Signup to reply.
  2. If you have confirmed that the value ‘doctor’ is being passed correctly to the MedProviderScreen and assigned to the medProviderType variable, then the issue may lie elsewhere. Here are a few possible causes to investigate:

    1. Make sure that the getProvidersData() method in your
      MedicalProviderController is being called and executed properly. You
      can add print statements or use debugging tools to verify if the
      method is being triggered and if the medicalProviderType variable
      has the expected value.

    2. Check if the
      FirebaseDatabase.instance.ref().child(‘medical_provider’).child(medicalProviderType!)
      path exists in your Firebase Realtime Database. Ensure that the
      database structure matches the path you’re using to fetch the data.

    3. Verify that the data retrieval from Firebase is successful and that
      the providerData variable in the getProvidersData() method contains
      the expected values. You can add print statements or use debugging
      tools to inspect the retrieved data and ensure it matches your
      database structure.

    4. Ensure that the MedProviderScreen widget is properly instantiated
      and the medProviderType value is passed correctly from the previous
      screen. Double-check if any other code modifications or updates
      might be interfering with the correct passing of the medProviderType
      value.

    By thoroughly investigating these aspects, you should be able to pinpoint the cause of the issue and resolve the "Null check operator used on a null value" error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search