Bloc: Need to create a bloc that is local to a screen

Created on 5 Nov 2020  ยท  2Comments  ยท  Source: felangel/bloc

Hi

i am trying to create a bloc that is needed only while a screen is being presented.

The screen code is as follow:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';
import 'city_search/address_search.dart';
import 'city_search/place_services.dart';
import 'weather_info/weather_item.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pack_me/blocs/weather/weather_bloc.dart';

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

static const routeName = '/trip';

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

class _TripWidgetState extends State {

DateTime _startDate = DateTime.now();
DateTime _endDate = DateTime.now();

TextEditingController _tripNameController = TextEditingController();

List _destinationsWidgets = List();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: BlocProvider(
create: (BuildContext context) => WeatherBloc(),
lazy: false,

child: SafeArea(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height0.6,
margin: EdgeInsets.only(top:0, left: 10,right: 10),
child: Card(
child: Container(
margin: EdgeInsets.only(right: 10,left: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Align(
alignment: Alignment.center,
child: Text("Trip Information",style: Theme.of(context).textTheme.headline4,),
),
//SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: Text("Name your trip:",style: Theme.of(context).textTheme.headline6,),
),
Align(
alignment: Alignment.topRight,
child: SizedBox(
width: 170,
child: TextField(
controller: _tripNameController,
style: Theme.of(context).textTheme.headline6,
decoration: InputDecoration(
hintText: "Trip name here",
),
),
)
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: Text("Start Date:",style: Theme.of(context).textTheme.headline6,),
),
Align(
alignment: Alignment.topRight,
child: Text("${_startDate.toLocal()}".split(' ')[0],style: Theme.of(context).textTheme.headline6),
),
Align(
alignment: Alignment.topRight,
child: IconButton(
icon: Icon(Icons.event),
onPressed: () => _selectDate(context,true),
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: Text("End Date: ",style: Theme.of(context).textTheme.headline6,),
),
Align(
alignment: Alignment.topRight,
child: Text("${_endDate.toLocal()}".split(' ')[0],style: Theme.of(context).textTheme.headline6),
),
Align(
alignment: Alignment.topRight,
child: IconButton(
icon: Icon(Icons.event),
onPressed: () => _selectDate(context,false),
),
)
],
),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Align(
alignment: Alignment.topLeft,
child: Text("Your Destination(s)",style: Theme.of(context).textTheme.headline6,),
),
Align(
alignment: Alignment.topRight,
child: IconButton(
icon: Icon(Icons.add_box),
onPressed: () => _addDestinationsToList(context),
),
),
],
),
Container(
width: 250,
height: 100,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: _destinationsWidgets,
),
),
)
],
),
],
),
),
),
),
Container(
height: MediaQuery.of(context).size.height
0.18,
//color: Colors.red,
margin: EdgeInsets.only(top:10, left: 10,right: 10),
child: _buildWeatherForcastInfo(),
),
SizedBox(height: 10,),
ElevatedButton(
child: Text("CREATE TRIP",style: Theme.of(context).textTheme.button.copyWith(color: Colors.white),),
onPressed: () => _tempFunction(),
)
],
),
),
),
);
}

_tempFunction() async {
BlocProvider.of(context).add(UpdateForecast("city"));
}

_buildWeatherForcastInfo() {
return Container(
child: ListView.builder(
itemCount: 5,
scrollDirection: Axis.horizontal,
itemBuilder: (context,index) => WeatherItem(),
),
);
}

_addDestinationsToList(BuildContext context) async {

final sessionToken = Uuid().v4();
final Suggestion result = await showSearch(
  context: context,
  delegate: AddressSearch(sessionToken)
);

//final place = await PlaceApiProvider(sessionToken).getPlaceDetailFromId(result.placeId)

InkWell inkWell = InkWell(
  child: Text(result.description,style: Theme.of(context).textTheme.subtitle1,),
  onTap: () => print(result.description),
);
setState(() {
  _destinationsWidgets.add(inkWell);
});

}

_selectDate(BuildContext context,bool isStartDate) async{
final ThemeData theme = Theme.of(context);
assert(theme.platform != null);
switch (theme.platform) {
case TargetPlatform.android:
return _buildMaterialDatePicker(context, isStartDate);
case TargetPlatform.iOS:
return _buildCupertinoDatePicker(context, isStartDate);
}
}

_buildMaterialDatePicker(BuildContext context,bool isStartDate) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: isStartDate == true ? _startDate : _endDate,
firstDate: DateTime(2020),
lastDate: DateTime(2025),
helpText: isStartDate == true ? "Select Start Date" : "Select End Date"
);
if (picked != null) {
setState(() {
if (isStartDate)
_startDate = picked;
else
_endDate = picked;
});
}
}

_buildCupertinoDatePicker(BuildContext context,bool isStartDate) {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height / 3,
color: Colors.white,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (picked) {
if (picked != null) {
setState(() {
if (isStartDate)
_startDate = picked;
else
_endDate = picked;
});
}
},
initialDateTime: isStartDate == true ? _startDate : _endDate,
minimumYear: 2020,
maximumYear: 2025,
),
);
}
);
}

}

please observe the two usages for BlocProvider.

i am getting the following error:
[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: BlocProvider.of() called with a context that does not contain a Cubit of type WeatherBloc.
No ancestor could be found starting from the context that was passed to BlocProvider.of().

    This can happen if the context you used comes from a widget above the BlocProvider.

    The context used was: TripWidget(dependencies: [MediaQuery, _LocalizationsScope-[GlobalKey#50b59], _InheritedTheme], state: _TripWidgetState#af91e)

0 BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:113:7)

1 _TripWidgetState._tempFunction (package:pack_me/screens/trip_widget/trip_widget.dart:168:18)

2 _TripWidgetState.build. (package:pack_me/screens/trip_widget/trip_widget.dart:158:34)

3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:985:20)

4 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:1101:38)

5 Gestur<โ€ฆ>

i hope someone can help me understand what am i doing wrong

Thanks much

question

Most helpful comment

thanks that did the trick

On Fri, Nov 6, 2020 at 12:18 PM Felix Angelov notifications@github.com
wrote:

Hi @pazhut https://github.com/pazhut ๐Ÿ‘‹
Thanks for opening an issue!

If you want to create a bloc that is only accessible in one widget then
you can create it in the initState of your State class and close it in
dispose and then reference the single instance as needed:

class MyWidget extends StatefulWidget {

@override

_MyWidgetState createState() => _MyWidgetState();

}

class _MyWidgetState extends State {

MyBloc _myBloc;

@override

void initState() {

super.initState();

_myBloc = MyBloc();

}

@override

void dispose() {

_myBloc.close();

super.dispose();

}

@override

Widget build(BuildContext context) {

return BlocBuilder(

  cubit: _myBloc,

  builder: (context, state) {

    // return some widgets

    // later you can add events to the bloc via: _myBloc.add(MyEvent());

  },

);

}

}

Hope that helps!

Closing for now but feel free to comment with additional questions and I'm
happy to continue the conversation ๐Ÿ‘

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/felangel/bloc/issues/1887#issuecomment-723198991, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/ANFZIGKMRTL46UHQLC47IUTSOQVXTANCNFSM4TL46C2A
.

All 2 comments

Hi @pazhut ๐Ÿ‘‹
Thanks for opening an issue!

If you want to create a bloc that is only accessible in one widget then you can create it in the initState of your State class and close it in dispose and then reference the single instance as needed:

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  MyBloc _myBloc;

  @override
  void initState() {
    super.initState();
    _myBloc = MyBloc();
  }

  @override
  void dispose() {
    _myBloc.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder(
      cubit: _myBloc,
      builder: (context, state) {
        // return some widgets
        // later you can add events to the bloc via: _myBloc.add(MyEvent());
      },
    );
  }
}

Hope that helps!

Closing for now but feel free to comment with additional questions and I'm happy to continue the conversation ๐Ÿ‘

thanks that did the trick

On Fri, Nov 6, 2020 at 12:18 PM Felix Angelov notifications@github.com
wrote:

Hi @pazhut https://github.com/pazhut ๐Ÿ‘‹
Thanks for opening an issue!

If you want to create a bloc that is only accessible in one widget then
you can create it in the initState of your State class and close it in
dispose and then reference the single instance as needed:

class MyWidget extends StatefulWidget {

@override

_MyWidgetState createState() => _MyWidgetState();

}

class _MyWidgetState extends State {

MyBloc _myBloc;

@override

void initState() {

super.initState();

_myBloc = MyBloc();

}

@override

void dispose() {

_myBloc.close();

super.dispose();

}

@override

Widget build(BuildContext context) {

return BlocBuilder(

  cubit: _myBloc,

  builder: (context, state) {

    // return some widgets

    // later you can add events to the bloc via: _myBloc.add(MyEvent());

  },

);

}

}

Hope that helps!

Closing for now but feel free to comment with additional questions and I'm
happy to continue the conversation ๐Ÿ‘

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/felangel/bloc/issues/1887#issuecomment-723198991, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/ANFZIGKMRTL46UHQLC47IUTSOQVXTANCNFSM4TL46C2A
.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rsnider19 picture rsnider19  ยท  3Comments

1AlexFix1 picture 1AlexFix1  ยท  3Comments

RobPFarley picture RobPFarley  ยท  3Comments

timtraversy picture timtraversy  ยท  3Comments

MahdiPishguy picture MahdiPishguy  ยท  3Comments