Fluttere Bloc problem with emit new state - flutter

I have a problem with Bloc. I would like to pass an event as in the code below. When I enter a new location it prints me the exact address but when I want to display it shows that I don't have it :(.
Could someone advise me something ?
void _onJourneyLocationEditing(
JourneyLocationEditing event,
Emitter<JourneyPointState> emit,
) {
emit(
state.copyWith(
point: event.location,
),
);
print('event.point.location');
print(event.location);
}
print = "JourneyPoint(, null, 1613 Amphitheatre Pkwy, Mountain View, CA 94043, USA)"
void _onFetchJourneyPoint(
FetchJourneyPoint event,
Emitter<JourneyPointState> emit,
) {
final startAt = event.point.startAt;
emit(
state.copyWith(
point: event.point,
time: startAt == null ? null : TimeOfDay.fromDateTime(startAt),
date: startAt,
),
);
print('event.point.location');
print(event.point.location);
}
print = ""

Related

Flutter Bloc emit problem with pass new property

In my application, I am trying to pass an address downloaded from Google Maps.
void _onJourneyLocationEditing(
JourneyLocationEditing event,
Emitter<JourneyPointState> emit,
) {
emit(
state.copyWith(
point: state.point.copyWith(
location: event.location,
),
),
);
}
print = 'JourneyPointState(JourneyPoint(, null, 419 Les Penons, 18100 Méry-sur-Cher, France)'
void _onFetchJourneyPoint(
FetchJourneyPoint event,
Emitter<JourneyPointState> emit,
) {
final startAt = event.point.startAt;
emit(
state.copyWith(
point: event.point,
time: startAt == null ? null : TimeOfDay.fromDateTime(startAt),
date: startAt,
),
);
}
print = 'JourneyPointState(JourneyPoint(Activity test, 2023-02-16 07:41:00.000, )'
Without my passed location parameter. Anyone knows what is the cause of this ?

Flutter BlocTest MissingStubError

Trying to test my cubit but i keep getting this error
MissingStubError: 'fetchOrganisationCountWithFilter'
No stub was found which matches the arguments of this method call:
fetchOrganisationCountWithFilter(QueryFilterOr(null, null, null, null, [QueryFilterElement(name, FilterOperation.matchPhrase, Mock Organisation, null, null), QueryFilterElement(domain, FilterOperation.eq, mock.com, null, null)]))
Here is the bloc test
void blocTestFetchOrganisationCount() {
blocTest<OrganisationFormCubit, OrganisationFormState>(
'Given a valid organisation, '
'when fetching organisation count, '
'then return 0',
build: () => _organisationFormCubit,
act: (cubit) async {
when(_organisationRepo.fetchOrganisationCountWithFilter(
QueryFilterOr(
[
QueryFilterElement(
'name',
FilterOperation.matchPhrase,
mockOrganisation.name,
),
if (mockOrganisation.domain != null)
QueryFilterElement(
'domain',
FilterOperation.eq,
mockOrganisation.domain,
),
],
),
)).thenAnswer((_) => Future(() => Success(0)));
await cubit.fetchOrganisationCount(mockOrganisation);
},
expect: _expectProcessingStateEmitted,
);
}
And here is the method that's not matching
#override
Future<Result<int>> fetchOrganisationCountWithFilter(
QueryFilter filter,
) async {
final response = await _organisationApi.countWithFilter(filter);
if (response.hasError) {
final error = response.error;
return Failed(Exception('${error.code!} ${error.message!}'));
}
return Success<int>(response.item);
}
Not sure how to fix it or make it work, spent way too long trying to figure out what's wrong but couldn't , any help is appreciated!

Getting Null error while trying to display data from my api response

I am having a currency picker, which onSelect I want to fetch some records based on the selected currency and display the data in a text widget.
So my endpoint url will be like this wwww.fetchrecordbasedoncurrency?curr=${selectedCurrency}
This is the currency picker
ElevatedButton(
onPressed: () {
Navigator.pop(context);
showCurrencyPicker(
context: context,
showFlag: true,
showSearchField: true,
showCurrencyName: true,
showCurrencyCode: true,
onSelect: (Currency currency) {
setState(() {
fetchData();
});
fetchData();
},
currencyFilter: <String>[
'AUD',
'CAD',
'EUR',
'USD'
],
favorite: ['USD'],
);
},
child: const Text('Select Payment Currency'),
),
This is the method responsible for fetching the data
void fetchData() async {
try {
setState(() {
isLoading = true;
});
var response = await networkHandler.get(
networkHandler.url + 'fetch-data.php?curr=${currencyType}');
getBankInfo = BankInfo.fromJson(response);
print("Bank Currency: ${getBankInfo.bank!.currency}");
} catch (ex) {
print({ex, 'An error occured while fetching bank data'});
} finally {
setState(() {
isLoading = false;
});
}
}
It fetches the data successfully, but I get this error Null check operator used on a null value
on the widget below which is trying to display a record based on the selected currency
Text('${getBankInfo.bank!.name}')
Hey you are getting this error in ${getBankInfo.bank!.name}. This error is because you are getting getBankInfo.bank is null and by using ! you are making it non-nullable. If you want to avoid this error then you can use ? instead of !, but by using ? if getBankInfo.bank is null then you will see null on screen. You can use null aware operator also like this getBankInfo.bank?.name ?? "".
You need to debug this line also getBankInfo = BankInfo.fromJson(response); to confirm you are getting right data or not to parse json

How to read StateNotifierProvider.family without passing value?

I have implemented StateNotifierProvider with ".family" modifier:
class OrderReviewNotifier extends StateNotifier<OrderReviewState> {
final OrderReviewRepository repository;
OrderReviewNotifier(
this.repository,
int orderId,
) : super(OrderReviewState.initial(orderId));
Future<void> getOrderItems() async {
//.....
}
}
final orderReviewProvider = StateNotifierProvider.autoDispose
.family<OrderReviewNotifier, OrderReviewState, int>(
(ref, orderId) {
return OrderReviewNotifier(
ref.watch(orderReviewRepositoryProvider),
orderId,
);
},
);
Then in Consumer I watch it:
Consumer(
builder: (context, watch, child) {
final state = watch(orderReviewProvider(order.id));
//.....
},
);
But when I want to read it, I need to pass order.id too:
onTap: () {
context
.read(orderReviewProvider(order.id).notifier)
.getOrderItems();
},
When I want to send events to notifier from another file, I don't have order.id.
How to get out of this situation?
Thanks for any help!
I figured out.
All I needed was StateProvider.
final selectedOrderProvider = StateProvider<Order?>((ref) => null);
Then in orderReviewProvider I can easily get orderId.
final orderReviewProvider =
StateNotifierProvider.autoDispose<OrderReviewNotifier, OrderReviewState>(
(ref) {
return OrderReviewNotifier(
ref.read,
orderId: ref.watch(selectedOrderProvider).state!.id,
repository: ref.watch(orderReviewRepositoryProvider),
);
},
);
class OrderReviewNotifier extends StateNotifier<OrderReviewState> {
OrderReviewNotifier(
this.read, {
required int orderId,
required this.repository,
}) : super(OrderReviewState.initial(orderId)) {
getOrderItems();
}
final Reader read;
final OrderReviewRepository repository;
Future<void> getOrderItems() async {
state = state.copyWith(
isLoading: true,
error: null,
);
final result = await repository.getOrderItems(state.orderId);
final checkedItemIds = await repository.getCheckedItemIds(state.orderId);
if (!mounted) {
return;
}
result.when(
data: (data) {
final isAllItemsChecked = !checkedItemIds.containsValue(false) &&
checkedItemIds.length >= data.length;
state = state.copyWith(
orderItems: data,
checkedItemIds: checkedItemIds,
isAllItemsChecked: isAllItemsChecked,
);
},
error: (message) {
state = state.copyWith(
error: message,
);
},
);
state = state.copyWith(
isLoading: false,
);
}
}
The documentation describes the work with this well: link.

notifyListeners in flutter not working, i.e. the value is not at all updated

below is the code where for my UserProvider. The commented line in it is for the testing purpose and when it was used, I got the username as "test" in output on screen.
class UserProvider with ChangeNotifier {
// UserModel _user = UserModel(username: "test", isLoggedIn: false, isVerified: false);
UserModel _user;
setUser(UserModel user)
{
_user = user;
notifyListeners();
print("user data changed !");
}
UserModel get getUser => _user;
}
Below is How I am updating data via a api call:
UserProvider().setUser(
UserModel(
username: user['username'] ?? 'Guest',
email: user['id'] != null ? user['email'] : 'not available',
avatar: user['id'] != null ? user['avatar'] : 'not available',
),
);
there are not error in runtime and I have a line in the setUser method which is there to check if the method was called or not print("user data changed !"). and in terminal I do get this line out put, so the function is not skipped and definitely called.
on screen I am calling the data as below:
UserModel user;
#override
void didChangeDependencies() {
user = Provider.of<UserProvider>(context).getUser;
super.didChangeDependencies();
}
and
Text("Hi, ${user.username}"),
Output is not the new data. its either NULL if the commented line is not used, and if used, the username is test.
So where am I going wrong?
All help is appreciated.
Thank you for going through my question.
Regarding this line of codes in your question
UserProvider().setUser(
UserModel(
username: user['username'] ?? 'Guest',
email: user['id'] != null ? user['email'] : 'not available',
avatar: user['id'] != null ? user['avatar'] : 'not available',
),
);
where are you using it?, because it seems it creates new UserProvider() everytime when it is called...
Make sure it's called from the right place something like shown in official docs here https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => UserProvider(),
child: MyApp(),
),
);
}