Bloc: Bloc listener not responding

Created on 19 Aug 2020  路  15Comments  路  Source: felangel/bloc

Screenshot 2020-08-19 at 9 08 15 AM

I implemented a Bloclistener on a button that calls a Finished registration event which save the patient to firebase and some of the fields to sembast(local database ) but after the event is dispatch in debug mode I see the state are emmitted but it seem the listener is not reacting to any of response declared nothing happens on the UI

question

All 15 comments

also I am using bloc 5.0.0 and flutter_bloc 5.0.0
since I am not yet familiar with cubit and bloc 6.0.0

Hi @davidAg9 馃憢
Thanks for opening an issue!

Can you verify that you only have a single instance of the bloc? I'm guessing you are creating multiple instances of the bloc and so the listener is listening to a different instance than the one you are interacting with. If that doesn't help, could you please provide a link to a sample app which reproduces the issue? Thanks 馃憤

What exactly do you mean by instance of bloc ; do you mean create an bloc provider in on screen/ wigdet and creating another provider in a widget below it in another screen down the previous widget with the same bloc?

I have invited to the repo to have a look at the issue

`import 'dart:io';

import 'package:date_format/date_format.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flushbar/flushbar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart';
import 'package:rokcare/bloc/patient_register_bloc/patient_registration_bloc.dart';
import 'package:rokcare/models/patient.dart';
import 'package:rokcare/repositories/firebase/storage.dart';

import 'components/bloodtypeDrop.dart';

class PatientForm extends StatefulWidget {
@override
_PatientFormState createState() => _PatientFormState();
}

class _PatientFormState extends State {
final GlobalKey _patientFormKey = GlobalKey();
final GlobalKey _residenceFormKey = GlobalKey();
final GlobalKey _medicalInfoFormKey = GlobalKey();

String _img = '';
final picker = ImagePicker();
bool male = false;
bool female = false;
DateTime _selectedDate = DateTime.now();
String _selectedsex = '';
int index = 0;
bool photoLoading = false;
Patient pat = Patient();
@override
Widget build(BuildContext context) {
final String formatDob = formatDate(_selectedDate, [yyyy, '-', M, '-', dd]);
return BlocProvider(
create: (BuildContext context) => PatientRegistrationBloc(),
child: BlocBuilder(
builder: (context, state) => SafeArea(
child: DefaultTabController(
initialIndex: index,
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text(
'Medical Form',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
bottom: TabBar(tabs: [
Tab(
text: 'Personal information',
icon: Icon(Icons.person),
),
Tab(
text: 'Residence',
icon: Icon(Icons.home),
),
Tab(
text: 'Medical Infomation',
icon: Icon(Icons.local_hospital),
)
]),
),
extendBody: true,
body: TabBarView(children: [
Container(
height: 380,
child: Form(
onChanged: () => _residenceFormKey.currentState.save(),
key: _residenceFormKey,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'Sur Name',
border: OutlineInputBorder(),
),
onSaved: (newValue) =>
pat.info.name.lastName = newValue,
),
SizedBox(
height: 10.0,
),
TextFormField(
decoration: InputDecoration(
labelText: 'First Name',
border: OutlineInputBorder()),
onSaved: (value) =>
pat.info.name.firstName = value,
),
SizedBox(
height: 10.0,
),
TextFormField(
decoration: InputDecoration(
labelText: 'Other names',
border: OutlineInputBorder()),
onSaved: (value) =>
pat.info.name.otherNames = value,
),
SizedBox(
height: 10.0,
),
TextFormField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'Phone Number',
border: OutlineInputBorder()),
onSaved: (value) =>
pat.info.contactInfo.phoneNumber = value,
),
SizedBox(
height: 10.0,
),
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Alternative Email',
border: OutlineInputBorder()),
onSaved: (value) => pat.info.email = value,
),
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(right: 50),
child: FlatButton(
color: Colors.blueGrey[200],
onPressed: () {
if (Platform.isAndroid) {
return androidDate(context);
} else if (Platform.isIOS) {
return iosDate(context);
}
},
child: ListTile(
leading: Icon(Icons.calendar_today),
title: Text('Date of Birth'),
subtitle: Text('$formatDob'),
trailing: Icon(Icons.arrow_drop_down_circle),
),
),
),
SizedBox(
height: 15.0,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Gender',
style: TextStyle(
fontSize: 20,
color: Colors.grey[700],
fontWeight: FontWeight.w600),
),
),
SizedBox(
height: 10.0,
),
Row(
children: [
GestureDetector(
onTap: () {
setState(() {
male = true;
female = false;
_selectedsex = 'male';

                                  pat.info.sex = _selectedsex;
                                });
                              },
                              child: Container(
                                decoration: BoxDecoration(
                                    color: male
                                        ? Colors.teal[500]
                                        : Colors.grey[300],
                                    borderRadius: BorderRadius.all(
                                        Radius.circular(30))),
                                height: 60,
                                width: 120,
                                child: Center(
                                    child: Text(
                                  'Male',
                                  style: TextStyle(
                                      fontWeight: FontWeight.w500,
                                      fontSize: 22),
                                )),
                              ),
                            ),
                            SizedBox(
                              width: 30,
                            ),
                            GestureDetector(
                              onTap: () {
                                setState(() {
                                  male = false;
                                  female = true;
                                  _selectedsex = 'female';
                                  pat.info.sex = _selectedsex;
                                });
                              },
                              child: Container(
                                decoration: BoxDecoration(
                                    color: female
                                        ? Colors.teal[500]
                                        : Colors.grey[300],
                                    borderRadius: BorderRadius.all(
                                        Radius.circular(30))),
                                height: 60,
                                width: 140,
                                child: Center(
                                    child: Text(
                                  'Female',
                                  style: TextStyle(
                                      fontWeight: FontWeight.w500,
                                      fontSize: 22),
                                )),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
            Container(
              height: 100,
              child: Form(
                onChanged: () => _patientFormKey.currentState.save(),
                key: _patientFormKey,
                child: SingleChildScrollView(
                  child: Padding(
                    padding: const EdgeInsets.all(10.0),
                    child: Column(
                      children: <Widget>[
                        TextFormField(
                          decoration: InputDecoration(
                              labelText: 'Address 1',
                              border: OutlineInputBorder()),
                          onSaved: (value) =>
                              pat.info.contactInfo.addressLine = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          decoration: InputDecoration(
                            labelText: 'Address 2',
                            border: OutlineInputBorder(),
                          ),
                          onSaved: (value) =>
                              pat.info.contactInfo.addressLine2 = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          decoration: InputDecoration(
                              labelText: 'City',
                              hintText: 'Accra',
                              border: OutlineInputBorder()),
                          onSaved: (value) =>
                              pat.info.contactInfo.city = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          keyboardType: TextInputType.emailAddress,
                          decoration: InputDecoration(
                              labelText: 'Region',
                              hintText: 'Greater Accra',
                              border: OutlineInputBorder()),
                          onSaved: (value) =>
                              pat.info.contactInfo.state = value,
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
            Container(
              height: 580,
              child: Form(
                key: _medicalInfoFormKey,
                onChanged: () => _medicalInfoFormKey.currentState.save(),
                child: SingleChildScrollView(
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: Column(
                      children: <Widget>[
                        SizedBox(
                          height: 10,
                        ),
                        Container(
                          decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(16),
                              border: Border.all(),
                              image: DecorationImage(
                                image: NetworkImage(_img ??
                                    'http://www.european-athletics.org/imgml/athletes/man-placeholder.jpg'),
                              )),
                          height: 86,
                          width: 102,
                          child: Stack(children: <Widget>[
                            Padding(
                              padding: const EdgeInsets.symmetric(
                                  vertical: 1, horizontal: 1),
                              child: Align(
                                alignment: Alignment.bottomRight,
                                child: GestureDetector(
                                  onTap: () async {
                                    setState(() {
                                      photoLoading = true;
                                    });

                                    await getImage()
                                        .then((value) => this.setState(() {
                                              photoLoading = false;
                                            }));
                                  },
                                  child: Container(
                                    decoration: BoxDecoration(
                                      borderRadius:
                                          BorderRadius.circular(20),
                                      color: Colors.blue,
                                    ),
                                    width: 32,
                                    height: 38,
                                    child: Center(
                                      child: Icon(
                                        Icons.add_a_photo,
                                        color: Colors.white,
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ]),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(vertical: 10),
                          child: photoLoading
                              ? CircularProgressIndicator()
                              : Text(
                                  'Select a Passport picture',
                                  style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: 15,
                                  ),
                                ),
                        ),
                        Align(
                          alignment: Alignment.center,
                          child: BloodType(
                              patientBlood: pat.medicalInfo.bloodtype),
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          keyboardType: TextInputType.number,
                          decoration: InputDecoration(
                              labelText: 'Height(cm)',
                              border: OutlineInputBorder()),
                          onSaved: (value) =>
                              pat.medicalInfo.height = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          keyboardType: TextInputType.number,
                          decoration: InputDecoration(
                              labelText: 'Weight(kg)',
                              border: OutlineInputBorder()),
                          onSaved: (value) =>
                              pat.medicalInfo.weight = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          keyboardType: TextInputType.phone,
                          decoration: InputDecoration(
                            labelText: 'Emergency Contact',
                            border: OutlineInputBorder(),
                          ),
                          onSaved: (value) =>
                              pat.emergencyContact.number = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          decoration: InputDecoration(
                            labelText: 'Emergency Contact name',
                            border: OutlineInputBorder(),
                          ),
                          onSaved: (value) =>
                              pat.emergencyContact.name = value,
                        ),
                        SizedBox(
                          height: 10.0,
                        ),
                        TextFormField(
                          decoration: InputDecoration(
                            labelText: 'Emergency Contact Relationship',
                            border: OutlineInputBorder(),
                          ),
                          onSaved: (value) =>
                              pat.emergencyContact.relation = value,
                        ),
                        SizedBox(
                          height: 16,
                        ),
                        BlocListener<PatientRegistrationBloc,
                            PatientRegistrationState>(
                          listener: (context, state) {
                            if (state is PFinishingRegistration)
                              return CircularProgressIndicator();
                            else if (state
                                is PRegistrationFinalizationFailure)
                              return Flushbar(
                                title: 'REGISTRATION FAILED',
                                message: 'Unable to Finish Registration',
                                icon: Icon(
                                  Icons.warning,
                                  color: Colors.red,
                                ),
                                duration: Duration(seconds: 4),
                                backgroundGradient: LinearGradient(
                                    colors: [Colors.white70, Colors.teal]),
                              );
                            else if (state is PFinishedRegistration)
                              return Navigator.of(context)
                                  .popAndPushNamed('/patientDashBoard');
                          },
                          child: GestureDetector(
                            onTap: () {
                              BlocProvider.of<PatientRegistrationBloc>(
                                  context)
                                ..add(PFinishRegistration(patient: pat));
                            },
                            child: Align(
                              alignment: Alignment.centerRight,
                              child: Container(
                                decoration: BoxDecoration(
                                    color: Colors.teal[300],
                                    borderRadius: BorderRadius.all(
                                        Radius.circular(30))),
                                height: 60,
                                width: 120,
                                child: Center(
                                    child: Text(
                                  'ENROLL',
                                  style: TextStyle(
                                      fontWeight: FontWeight.w500,
                                      fontSize: 22),
                                )),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ]),
        ),
      ),
    ),
  ),
);

}

androidDate(BuildContext context) async {
showDatePicker(
initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now(),
context: context,
initialEntryMode: DatePickerEntryMode.calendar,
).then((value) {
this.setState(() {
_selectedDate = value;
pat.info.dob = value;
});
});
}

iosDate(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height,
color: Colors.white,
child: Column(
children: [
Flexible(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (picked) {
if (picked != null && picked != _selectedDate)
setState(() {
_selectedDate = picked;
pat.info.dob = picked;
});
},
initialDateTime: _selectedDate,
minimumYear: 1900,
maximumYear: DateTime.now().year,
),
),
FlatButton(
child: Text('Done'),
onPressed: () => Navigator.pop(context),
color: Colors.green,
),
],
),
);
});
}

Future getImage() async {
photoLoading = true;
File docImg = await FilePicker.getFile(type: FileType.image);

StorageRepository img = StorageRepository();
img
    .saveFile(docImg, StoragePaths.Avatars)
    .then((value) => this.setState(() {
          _img = value;
          pat.info.photoUrl = value;
          photoLoading = false;
        }));

}
}
`

Hi @davidAg9 馃憢

Your code is incomplete and really hard for anyone to get it in a run-able state. Please create a minimal reproduction repository with your issue and share a link to it so we could run it locally 馃憤

I have gone through and I sent only the widget of where the listener was implemented
Do you want to to see how I implanted the bloc itself before implementation in the above widget ?,I have though given access to the repo to @felangel for review .

Still waiting for response ,if you need help navigating to the bloc and the where the error appears to occurs please lemme know
@felangel

Hi @davidAg9 I took a look and the issue is you are creating two different instances of the PatientRegistrationBloc

This means that the bloc that you are listening on is different from the bloc you are adding the events to. Please make sure to have a single instance of the bloc which you are adding events and consuming.

Closing for now but feel free to comment with additional questions and I'm happy to continue the conversation 馃憤

thank you will take a look at it and give you a response

you know its because of your overall character and commitment to the quality of your product that makes it so good .I am personally impressed and will be loyal to bloc as I believe its the best state management for flutter and should be implemented in other frameworks like django and the likes .

Screenshot 2020-08-23 at 7 44 50 AM
this is what happens if I take the patientregistrationBloc implementation from the PatientSignup widget.
I thought bloc works by a tree order so theoretically it should work since PatientSignUp widget is one level above the PatientForm so I don't get why it cannot find the instance because in learning the bloc I understood that once a bloc provider is instantiated any widget below where the bloc was instantiated can use that bloc
.if that is not the case please enlighten me .(how then will a bloc be scope or global if I am having such behaviour in my project)

Screenshot 2020-08-23 at 7 56 06 AM
this is how I wrote it

It I believe I have unraveled the issue ,so the issue is from a Firebase document its checking and of which its returning null which in turn throws an exception and does not allow the listener to execute tho I don't understand why the failed state to did not execute I am attempting to fix the issue with firebase to see If it will respond

Glad to hear you found the problem! What was the exception and how are you planning to address it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Reidond picture Reidond  路  3Comments

abinvp picture abinvp  路  3Comments

rsnider19 picture rsnider19  路  3Comments

MahdiPishguy picture MahdiPishguy  路  3Comments

ricktotec picture ricktotec  路  3Comments