How to change state of individual list items using bloc flutter? - flutter

How to change the widgets in a list item in flutter using bloc pacakage.
Should i use BlockBuilder or listener on the whole ListView.builder or only the individual items.
It would be nice if u share an example or tutorial.
eg If i have a checkbox i need to change its state on clicking it.
These are my Bloc classes
Bloc
const String SERVER_FAILURE_MESSAGE = 'Server Failure';
const String CACHE_FAILURE_MESSAGE = 'Cache Failure';
class MarkAttendanceBloc extends Bloc<MarkAttendanceEvent, MarkAttendanceState> {
final MarkStudentPresent markStudentPresent;
final MarkStudentAbsent markStudentAbsent;
MarkAttendanceBloc({#required this.markStudentPresent,#required this.markStudentAbsent});
#override
MarkAttendanceState get initialState => MarkedInitial();
#override
Stream<MarkAttendanceState> mapEventToState(MarkAttendanceEvent event) async* {
yield MarkedLoading();
if(event is MarkAbsentEvent){
final remotelyReceived = await markStudentAbsent(MarkStudentParams(classId: event.classId, courseId: event.courseId,studentId: event.studentId));
yield* _eitherLoadedOrErrorState(remotelyReceived);
}
else if(event is MarkPresentEvent){
final remotelyReceived = await markStudentPresent(MarkStudentParams(classId: event.classId, courseId: event.courseId,studentId: event.studentId));
yield* _eitherLoadedOrErrorState(remotelyReceived);
}
}
Stream<MarkAttendanceState> _eitherLoadedOrErrorState(
Either<StudentDetailsFacultyFailure,int> failureOrClasses,
) async* {
yield failureOrClasses.fold(
(failure) => MarkedError(_mapFailureToMessage(failure)),
(studentId) => Marked(studentId),
);
}
String _mapFailureToMessage(StudentDetailsFacultyFailure failure) {
switch (failure.runtimeType) {
case ServerError:
return SERVER_FAILURE_MESSAGE;
default:
return 'No internet';
}
}
}
State
abstract class MarkAttendanceState extends Equatable{
const MarkAttendanceState();
}
class MarkedInitial extends MarkAttendanceState{
const MarkedInitial();
#override
List<Object> get props => [];
}
class MarkedLoading extends MarkAttendanceState{
const MarkedLoading();
#override
List<Object> get props => [];
}
class Marked extends MarkAttendanceState{
final int studentId;
Marked(this.studentId);
#override
List<Object> get props => [studentId];
}
class MarkedError extends MarkAttendanceState{
final String errorMessage;
MarkedError(this.errorMessage);
#override
List<Object> get props => [errorMessage];
}
Event
import 'package:equatable/equatable.dart';
abstract class MarkAttendanceEvent extends Equatable {
const MarkAttendanceEvent();
}
class MarkPresentEvent extends MarkAttendanceEvent {
final int studentId;
final int courseId;
final int classId;
MarkPresentEvent(this.studentId, this.courseId, this.classId);
#override
List<Object> get props =>[studentId,courseId,classId];
}
class MarkAbsentEvent extends MarkAttendanceEvent {
final int studentId;
final int courseId;
final int classId;
MarkAbsentEvent(this.studentId, this.courseId, this.classId);
#override
List<Object> get props =>[studentId,courseId,classId];
}

Maybe by now you have found a solution but this is how i managed to achieve the same functionality using flutter cubits.
This code is hand written and not tested but it should guide you to achieve your goal
1 Declare the class objects
class ClassItem{
int? price;
bool isChecked;
ClassItem({
this.price,
this.isChecked=false,
});
}
class ClassOverall{
List<ClassItem> items;
double? total;
ClassOverall(this.items,this.total);
}
Declare the cubit class
class OverallCubit extends Cubit<ClassOverall> {
OverallCubit(ClassOverallinitialState) : super(initialState);
void checkUncheckCart(int index) {
if (!state.items
.elementAt(index).isChecked) {
state.items
.elementAt(index).isChecked =
!state.items
.elementAt(index).isChecked;
var t_total = double.tryParse(state.items
.elementAt(index).price!)! * 1;
emit(OverallCubit (state.items,state.total));
} else {
state.items.elementAt(index).isChecked =
!state.items
.elementAt(index).isChecked;
emit(OverallCubit (state.items,state.total));
}
calculateTotal();
}
void calculateTotal() {
var tot = 0.0;
for (var tick in state.items) {
if (tick.isChecked) {
tot = (tick.t_total! + tot);
}
}
emit(OverallCubit (state.items,tot));
}
}
Declare the top class widget to hold the state
class TopState extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => OverallCubit(ClassOverall(items,0)),//fetch items from your source
child: Home(),
);
}
}
Declare the stateful widget and add a bloc builder
class Home extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<Home> {
#override
Widget build(BuildContext context) {
return BlocBuilder<OverallCubit, ClassOverall>(
builder: (ctx, state) {
return Column(children:[
ListView.builder(
padding: EdgeInsets.all(0.0),
shrinkWrap: true,
itemCount: state.items.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {
ctx
.read<OverallCubit>()
.checkUncheckCart(index);
},
tileColor: state.elementAt(index).isChecked ? Colors.red : Colors.white
title: Text(state.items.elementAt(index).price!),
);
}),
Text(state.total.toString),
]);
});
}
}

Related

how to use infinite_scroll_pagination for bloc pattern

I'm currently learning and converting my code to BLoc pattern. Before I'm using flutter_pagewise ^1.2.3 for my infinite scroll using Future<> but I don't know how to use it using bloc or is it compatible with it.
So now I'm trying infinite_scroll_pagination: ^2.3.0 since it says in its docs that it supports Bloc. But I don't understand the example code in the docs for bloc. Can you give me a simple example of how to use it with bloc? I'm currently using flutter_bloc: ^6.1.3.
Here are my bloc script:
class TimeslotViewBloc extends Bloc<TimeslotViewEvent, TimeslotViewState> {
final GetTimeslotView gettimeslotView;
TimeslotViewBloc({this.gettimeslotView}) : super(TimeslotViewInitialState());
#override
Stream<TimeslotViewState> mapEventToState(
TimeslotViewEvent event,
) async* {
if (event is GetTimeslotViewEvent) {
yield TimeslotViewLoadingState();
final failureOrSuccess = await gettimeslotView(Params(
id: event.id,
date: event.date,
));
yield* _eitherLoadedOrErrorState(failureOrSuccess);
}
}
Stream<TimeslotViewState> _eitherLoadedOrErrorState(
Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
) async* {
yield failureOrTrivia.fold(
(failure) => TimeslotViewErrorState(
message: _mapFailureToMessage(failure), failure: failure),
(result) => TimeslotViewLoadedState(result),
);
}
//Bloc Events----------------------------------------
abstract class TimeslotViewEvent extends Equatable {
const TimeslotViewEvent();
#override
List<Object> get props => [];
}
class GetTimeslotViewEvent extends TimeslotViewEvent {
final String id;
final String date;
final int offset;
final int limit;
GetTimeslotViewEvent(
{this.id,
this.date,
this.offset,
this.limit});
}
//Bloc States----------------------------------------
abstract class TimeslotViewState extends Equatable {
const TimeslotViewState();
#override
List<Object> get props => [];
}
class TimeslotViewLoadingState extends TimeslotViewState {}
class TimeslotViewLoadedState extends TimeslotViewState {
final List<TimeslotViewEntity> records;
TimeslotViewLoadedState(this.records);
#override
List<Object> get props => [records];
}
UPDATE: Here is the revised code from Davii that works for me
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _timeLotBloc,
child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
listener: (context, state) {
if (state is TimeslotViewLoadedState) {
//Save record count instead of records list
totalRecordCount += state.records.length;
final _next = 1 + totalRecordCount;
final isLastPage = state.records.length < PAGE_SIZE;
if (isLastPage) {
_pagingController.appendLastPage(state.records);
} else {
_pagingController.appendPage(state.records, _next);
}
}
if (state is TimeslotViewErrorState) {
_pagingController.error = state.error;
}
},
//Removed pagedListview from bloc builder
child: PagedListView<int, TimeslotViewEntity>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
character: time,
),
),
),),
);
}
class PaginatedList extends StatefulWidget {
const PaginatedList({Key? key}) : super(key: key);
#override
_PaginatedListState createState() => _PaginatedListState();
}
class _PaginatedListState extends State<PaginatedList> {
//*bloc assuming you use getIt and injectable
late final _timeLotBloc = getIt<TimeslotViewBloc>();
List<TimeslotViewEntity> records = [];
//*initialize page controller
final PagingController<int, TimeslotViewEntity> _pagingController =
PagingController(firstPageKey: 0);
#override
void initState() {
super.initState();
//*so at event add list of records
_pagingController.addPageRequestListener(
(pageKey) => _timeLotBloc
.add(GetTimeslotViewEvent(records: records, offset: pageKey,limit: 10)),
);
}
#override
void dispose() {
super.dispose();
_timeLotBloc.close();
_pagingController.dispose();
}
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => _timeLotBloc,
child: BlocListener<TimeslotViewBloc, TimeslotViewState>(
listener: (context, state) {
if (state is TimeslotViewLoadedState) {
records =state.records;
//forget about existing record
//about the last page, fetch last page number from
//backend
int lastPage = state.lastPage
final _next = 1 + records.length;
if(_next>lastPage){
_pagingController.appendLastPage(records);
}
else{
_pagingController.appendPage(records, _next);
}
}
if (state is TimeslotViewErrorState) {
_pagingController.error = state.error;
}
},child: BlocBuilder<TimeslotViewBloc,TimeslotViewState>(
builder: (context,state)=> PagedListView<int, TimeslotViewEntity>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<TimeslotViewEntity>(
itemBuilder: (context, time, index) => TimeslotViewEntityListItem(
character: time,
),
),
),),
),
);
}
}
now on the bloc event class
class GetTimeslotViewEvent extends TimeslotViewEvent {
final String id;
final String date;
final int offset;
final int limit;
//add this on event
final List<TimeslotViewEntity> records;
GetTimeslotViewEvent({
this.id,
this.date,
this.offset,
this.limit,
required this.records,
});
}
on state class
class TimeslotViewLoadedState extends TimeslotViewState {
final List<TimeslotViewEntity> records;
final List<TimeslotViewEntity> existingRecords;
TimeslotViewLoadedState(this.records, this.existingRecords);
#override
List<Object> get props => [records, existingRecords];
}
and on bloc now
yield* _eitherLoadedOrErrorState(failureOrSuccess,event);
Stream<TimeslotViewState> _eitherLoadedOrErrorState(
Either<Failure, List<TimeslotViewEntity>> failureOrTrivia,
GetTimeslotViewEvent event,
) async* {
yield failureOrTrivia.fold(
(failure) => TimeslotViewErrorState(
message: _mapFailureToMessage(failure), failure: failure),
//existing records from the event,
(result) => TimeslotViewLoadedState(result,event.records),
);
}
yap this method worked on me

When I use Bloc pattern My infinite list doesn't scroll

I want to make infinite list with bloc pattern but My bloc builder works only 1 time.After scroll the page "yield" doesn't work so bloc builder doesn't build.The new items comes but state doesn't build.
deliveries_bloc.dart:
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_asten_app/data/orders_repository.dart';
import 'package:flutter_asten_app/models/order_list.dart';
import '../../locater.dart';
part 'deliveries_event.dart';
part 'deliveries_state.dart';
class DeliveriesBloc extends Bloc<DeliveriesEvent, DeliveriesState> {
final OrdersRepository ordersRepository = getIt<OrdersRepository>();
DeliveriesBloc() : super(DeliveriesInitial());
List<OrderList> orderss = [];
#override
Stream<DeliveriesState> mapEventToState(
DeliveriesEvent event,
) async* {
if (event is FetchDeliveriesEvent) {
yield DeliveriesLoadingState();
try {
final orders = await ordersRepository.getOrderList(event.page);
print(orders.length);
yield DeliveriesLoadedState(orders: orders);
} catch (_) {
yield DeliveriesErrorState();
}
} else if (event is FetchMoreDeliveriesEvent) {
try {
final orders = await ordersRepository.getMoreOrderList(event.page);
print(orders.length); //this is for check the orders length
yield DeliveriesLoadedState(orders: orders);
} catch (_) {
yield DeliveriesErrorState();
}
}
}
}
You can see in the above when my event is FetchMoreDeliveriesEvent my orders lengths icreases but the yield DeliveriesLoadedState(orders: orders); doesn't work
deliveries_state.dart:
part of 'deliveries_bloc.dart';
abstract class DeliveriesState extends Equatable {
const DeliveriesState();
}
class DeliveriesInitial extends DeliveriesState {
#override
List<Object> get props => [];
}
class DeliveriesLoadingState extends DeliveriesState {
#override
// TODO: implement props
List<Object> get props => throw UnimplementedError();
}
class DeliveriesLoadedState extends DeliveriesState {
final List<OrderList> orders;
DeliveriesLoadedState({#required this.orders});
#override
// TODO: implement props
List<Object> get props => [orders];
}
class DeliveriesErrorState extends DeliveriesState {
#override
// TODO: implement props
List<Object> get props => throw UnimplementedError();
}
deliveries_event.dart:
part of 'deliveries_bloc.dart';
abstract class DeliveriesEvent extends Equatable {
const DeliveriesEvent();
}
class FetchDeliveriesEvent extends DeliveriesEvent {
final int page;
FetchDeliveriesEvent({#required this.page});
#override
// TODO: implement props
List<Object> get props => [page];
}
class FetchMoreDeliveriesEvent extends DeliveriesEvent {
final int page;
FetchMoreDeliveriesEvent({#required this.page});
#override
// TODO: implement props
List<Object> get props => [page];
}
the part of Main_page
Expanded(
child: BlocBuilder<DeliveriesBloc, DeliveriesState>(
bloc: _ordersBloc,
builder: (context, DeliveriesState state) {
if (state is DeliveriesLoadingState) {
return Center(
child: CircularProgressIndicator(),
);
}
if (state is DeliveriesLoadedState) {
return ListView.builder(
controller: _scrollController,
itemCount: state.orders.length,
itemBuilder: (context, index) {
return Card(
elevation: 4,
child: ListTile(
title: Text(state.orders[index].firadi),
subtitle: Text(state.orders[index].sidttr
.toString()),
),
);
});
} else {
return null;
}
},
),
),
Bloc builder re-build the widgets only if its content changes. Make sure you are providing your change detectable variables to your equatable's props getter.
If your OrderList class is not extending from Equatable, the orders fields change won't be reflected in state.
Check if you extended your OrderList class with Equatable, if yes make sure you added its props as well.

Error: Type argument 'RoutesBloc' doesn't conform to the bound 'BlocBase<S>' of the type variable 'B' on 'BlocBuilder'

I'm getting this error and I have no clue where it's coming from.
class Routes extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocBuilder<RoutesBloc, RoutesEvent>( // <-- It occurs here
builder: (context, state) {
return Text('...');
},
);
}
}
Full error:
lib/screens/home_screen.dart:86:12: Error: Type argument 'RoutesBloc' doesn't conform to the bound 'BlocBase' of the type variable 'B' on 'BlocBuilder'.
'RoutesBloc' is from '/blocs/routes/routes_bloc.dart' ('lib/blocs/routes/routes_bloc.dart').
'BlocBase' is from 'package:bloc/src/bloc.dart' ('../../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/bloc-7.0.0/lib/src/bloc.dart').
Try changing type arguments so that they conform to the bounds.
return BlocBuilder<RoutesBloc, RoutesEvent>(
^
I use a multiplocprovider in my main.dart like this:
MultiBlocProvider(
providers: [
...,
BlocProvider<RoutesBloc>(
create: (_) => RoutesBloc(
apiRepository: ApiRepository.create(),
)..add(RoutesLoaded()),
),
],
child: AppView(),
)
routes_state.dart:
abstract class RoutesState extends Equatable {
const RoutesState();
#override
List<Object> get props => [];
}
class RoutesLoadInProgress extends RoutesState {}
class RoutesLoadSuccess extends RoutesState {
final List<BoulderingRoute> routes;
const RoutesLoadSuccess([this.routes = const []]);
#override
List<Object> get props => [routes];
}
class RoutesLoadFailure extends RoutesState {}
routes_event.dart:
abstract class RoutesEvent extends Equatable {
const RoutesEvent();
#override
List<Object> get props => [];
}
class RoutesLoaded extends RoutesEvent {}
class RouteAdded extends RoutesEvent {
final BoulderingRoute route;
const RouteAdded({this.route}) : assert(route != null);
#override
List<Object> get props => [route];
}
class RouteUpdated extends RoutesEvent {
final BoulderingRoute route;
const RouteUpdated({this.route}) : assert(route != null);
#override
List<Object> get props => [route];
}
class RouteDeleted extends RoutesEvent {
final BoulderingRoute route;
const RouteDeleted({this.route}) : assert(route != null);
#override
List<Object> get props => [route];
}
routes_bloc.dart:
class RoutesBloc extends Bloc<RoutesEvent, RoutesState> {
final ApiRepository _apiRepository;
RoutesBloc({ApiRepository apiRepository})
: assert(apiRepository != null),
this._apiRepository = apiRepository,
super(RoutesLoadInProgress());
#override
Stream<RoutesState> mapEventToState(
RoutesEvent event,
) async* {
print(event);
if (event is RoutesLoaded) {
yield* _mapRoutesLoadedToState();
}
}
Stream<RoutesState> _mapRoutesLoadedToState() async* {
try {
print('start');
final List<BoulderingRoute> routes =
await _apiRepository.fetchBoulderingRoutes();
yield RoutesLoadSuccess(routes);
} catch (_) {
yield RoutesLoadFailure();
}
}
}
I firstly thought that there must be something wrong with my RoutesBloc but changing the blocbuilder to a bloc that I'm successfully using at another place ends up with the same error.
Does someone know where this is coming from?
It should be return BlocBuilder<RoutesBloc, RoutesState>
Check this: https://pub.dev/packages/flutter_bloc#blocbuilder
BlocBuilder<BlocA, BlocAState>(
builder: (context, state) {
// return widget here based on BlocA's state
}
)

Flutter Bloc How to update Widget in BlocBuilder from the Widget itself?

How can to update a Bloc widget from the bloc Widget itself with the Slider?
The Event for the Chart Data is executed from another Widget.
When the data is fetched this Widget is opened.
When I change the Slider I want the chart to be updated withe the date but keep the other data.
Would be too much to fetch all the Data again.
How can I get access only the data changed from the same widget?
I have the following Bloc Builder Widget, bloc_event, bloc and bloc_state
The Widget:
class ChartWidget extends StatelessWidget {
ChartWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
double valueSliderDate;
return BlocBuilder<ChartDataBloc, ChartDataState>(
builder: (context, state) {
if (state is ChartDataLoadInProgress) {
return LoadingIndicator();
} else if (state is ChartDataLoadSuccess) {
final chartData = state.chartData;
final maxValueAll = getMaxValueAll(chartData);
final List<double> dates = getValuesDate(chartData);
valueSliderDate = dates.first;
return Column(children: <Widget>[
Expanded(
child: MyFancyChart(chartData, valueSliderDate),
),
Slider(
min: dates.first,
max: dates.last,
divisions: dates.length,
value: valueSliderDate,
onChanged: (value) {
context.read<ChartDataBloc>().add(DateSliderSet(value));
},
),
]);
} else {
return Container();
}
},
);
}
This is the bloc_event with two events:
abstract class ChartDataEvent {
const ChartDataEvent();
#override
List<Object> get props => []; }
class SpecificIndicatorIdSet extends ChartDataEvent {
const SpecificIndicatorIdSet(this.indicator);
final Indicator indicator;
#override
List<Object> get props => [indicator]; }
class DateSliderSet extends ChartDataEvent {
const DateSliderSet(this.dateSlider);
final double dateSlider;
#override
List<Object> get props => [dateSlider]; }
This is the bloc itself:
class ChartDataBloc extends Bloc<ChartDataEvent, ChartDataState> {
final ChartDataRepository chartDataRepository;
ChartDataBloc({#required this.chartDataRepository}) : super(ChartDataLoadInProgress());
#override
Stream<ChartDataState> mapEventToState(ChartDataEvent event) async* {
if (event is SpecificIndicatorIdSet) {
yield* _mapIndicatorsLoadedToState(event);
} else if (event is DateSliderSet) {
yield* _mapDateSliderToState(event); } }
Stream<ChartDataState> _mapDateSliderToState(
DateSliderSet event
) async* {
try {
final dateSlider = event.dateSlider;
yield DateSliderLoadSuccess(
dateSlider,
);
} catch (_) {
yield DateSliderLoadFailure(); } }
Stream<ChartDataState> _mapIndicatorsLoadedToState(
SpecificIndicatorIdSet event
) async* {
try {
final chartData = await this.chartDataRepository.loadChartData(event.indicator.id);
yield ChartDataLoadSuccess(
sortToListOfLists(chartData),
event.indicator.name
);
} catch (_) {
yield ChartDataLoadFailure(); } } }
This is the bloc_state:
abstract class ChartDataState {
const ChartDataState();
#override
List<Object> get props => []; }
class ChartDataLoadInProgress extends ChartDataState {}
class ChartDataLoadSuccess extends ChartDataState {
final List<List<ChartData>> chartData;
final String titleIndicator;
const ChartDataLoadSuccess(this.chartData,this.titleIndicator);
#override
List<Object> get props => [chartData, titleIndicator];
#override
String toString() => 'ChartDataLoadSuccess { topics: ' + chartData + ' }'; }
class ChartDataLoadFailure extends ChartDataState {}
class DateSliderLoadSuccess extends ChartDataState {
final double dateSlider;
const DateSliderLoadSuccess(this.dateSlider);
#override
List<Object> get props => [dateSlider];
#override
String toString() => 'DateSliderLoadSuccess { dateSlider: ' + dateSlider.toString() + ' }';
}
class DateSliderLoadFailure extends ChartDataState {}
Thanks in advance
Have you tried creating a variable inside your bloc to store the original data?
You would be able to store the data and be able to continue using your bloc and updating your widget.

Data not being updated after change the placeID in flutter BLoC

I am working on one project with BLoC.I have made some classes to update the data.
Data will come once you pass the placeID.
But once you pass the PlaceID first time it will give the data and widgets updated.
But once I pass new placeID old data not being updated. It shows old data.
All Code Files:
RestaurantDetailBloc.dart
class RestaurantDetailBloc extends Bloc<RestaurantDetailEvent, RestaurantDetailState> {
static final RestaurantDetailBloc _restaurantDetailBlocSingleton = new RestaurantDetailBloc._internal();
factory RestaurantDetailBloc() {
return _restaurantDetailBlocSingleton;
}
RestaurantDetailBloc._internal();
RestaurantDetailState get initialState => new UnRestaurantDetailState();
#override
Stream<RestaurantDetailState> mapEventToState(
RestaurantDetailEvent event,
) async* {
try {
yield await event.applyAsync(currentState: currentState, bloc: this);
} catch (_, stackTrace) {
print('$_ $stackTrace');
yield currentState;
}
}
}
LoadRestaurantDetailEvent.dart
#immutable
abstract class RestaurantDetailEvent {
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc});
final RestaurantDetailProvider _provider = RestaurantDetailProvider();
}
class LoadRestaurantDetailEvent extends RestaurantDetailEvent {
#override
String toString() => 'LoadRestaurantDetailEvent';
String placeID;
LoadRestaurantDetailEvent({Key key,this.placeID});
#override
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc}) async {
try {
await Future.delayed(new Duration(seconds: 2));
var component = await _provider.getRestaurantReview(placeID);
print(component);
return new InRestaurantDetailState(component);
} catch (_, stackTrace) {
print('$_ $stackTrace');
return new ErrorRestaurantDetailState(_?.toString());
}
}
}
RestaurantDetailPage.dart
class RestaurantDetailPage extends StatelessWidget {
static const String routeName = "/restaurantDetail";
final String imageURL;
final String placeID;
const RestaurantDetailPage({Key key, this.imageURL,this.placeID}) : super(key: key);
#override
Widget build(BuildContext context) {
var _restaurantDetailBloc = new RestaurantDetailBloc();
return new RestaurantDetailScreen(restaurantDetailBloc: _restaurantDetailBloc,imageUrl: this.imageURL,placeId: this.placeID,);
}
}
RestaurantDetailProvider.dart
class RestaurantDetailProvider {
String getBaseUrl(String placeID){
final urlBase = "https://maps.googleapis.com/maps/api/place/details/json?placeid=$placeID&key=xxxxxxxxxxxxxGooglePlaceKey";
return urlBase;
}
Future<void> loadAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<void> saveAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<Map<String, dynamic>> getRestaurantReview(String placeId)async{
var response = await http.get(getBaseUrl(placeId));
RestaurantReviews reviews = RestaurantReviews();
if(response.statusCode == 200){
var decodedJson = jsonDecode(response.body);
print(decodedJson);
//reviews.result = decodedJson['result'];
return decodedJson;
}
else{
}
}
}
InRestaurantDetailState.dart
#immutable
abstract class RestaurantDetailState extends Equatable {
RestaurantDetailState([Iterable props]) : super(props);
/// Copy object for use in action
RestaurantDetailState getStateCopy();
}
/// UnInitialized
class UnRestaurantDetailState extends RestaurantDetailState {
#override
String toString() => 'UnRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return UnRestaurantDetailState();
}
}
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
InRestaurantDetailState(this.resReview);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}
class ErrorRestaurantDetailState extends RestaurantDetailState {
final String errorMessage;
ErrorRestaurantDetailState(this.errorMessage);
#override
String toString() => 'ErrorRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return ErrorRestaurantDetailState(this.errorMessage);
}
}
RestaurantDetailScreenState.dart
class RestaurantDetailScreen extends StatefulWidget {
const RestaurantDetailScreen({
Key key,
#required RestaurantDetailBloc restaurantDetailBloc,
this.imageUrl, this.placeId,
}) : _restaurantDetailBloc = restaurantDetailBloc,
super(key: key);
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
#override
RestaurantDetailScreenState createState() {
return new RestaurantDetailScreenState(_restaurantDetailBloc, imageUrl,placeId);
}
}
class RestaurantDetailScreenState extends State<RestaurantDetailScreen> {
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
RestaurantDetailScreenState(this._restaurantDetailBloc, this.imageUrl,this.placeId);
#override
void initState() {
super.initState();
this._restaurantDetailBloc.dispatch(LoadRestaurantDetailEvent(placeID:placeId));
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
return BlocBuilder<RestaurantDetailBloc, RestaurantDetailState>(
bloc: widget._restaurantDetailBloc,
builder: (
BuildContext context,
var currentState,
) {
if (currentState is UnRestaurantDetailState) {
return MaterialApp(
home: new Scaffold(
body: new Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
if (currentState is ErrorRestaurantDetailState) {
return new Container(
child: new Center(
child: new Text(currentState.errorMessage ?? 'Error'),
));
}
if (currentState is InRestaurantDetailState) {
var resList = currentState.resReview;
print(resList);
return MaterialApp(
home: new Scaffold(
)
);
}
Please help me guys.I have spent whole day.
Thank you in advance.
You need to pass the data to the parent class for comparison. That's why we are using equatable. Do these changes and it should work. Let me know if it doesn’t.
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
//You need to change this line to
InRestaurantDetailState(this.resReview):super([resReview]);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}