How to map each item from observable to another one that comes from async function? - flutter

I want to
1.map item from observable to another one if it has already saved in database.
2.otherwise, use it as it is.
and keep their order in result.
Saved item has some property like tag, and item from observable is 'raw', it doesn't have any property.
I wrote code like this and run testMethod.
class Item {
final String key;
String tag;
Item(this.key);
#override
String toString() {
return ('key:$key,tag:$tag');
}
}
class Sample {
///this will generate observable with 'raw' items.
static Observable<Item> getItems() {
return Observable.range(1, 5).map((index) => Item(index.toString()));
}
///this will find saved item from repository if it exists.
static Future<Item> findItemByKey(String key) async {
//simulate database search
await Future.delayed(Duration(seconds: 1));
if (key == '1' || key == '4') {
final item = Item(key)..tag = 'saved';
return item;
} else
return null;
}
static void testMethod() {
getItems().map((item) async {
final savedItem = await findItemByKey(item.key);
if (savedItem == null) {
print('not saved:$item');
return item;
} else {
print('saved:$savedItem');
return savedItem;
}
}).listen((item) {});
}
The result is not expected one.
expected:
saved:key:1,tag:saved
not saved:key:2,tag:null
not saved:key:3,tag:null
saved:key:4,tag:saved
not saved:key:5,tag:null
actual:
not saved:key:2,tag:null
not saved:key:3,tag:null
not saved:key:5,tag:null
saved:key:1,tag:saved
saved:key:4,tag:saved
How to keep their order in result?

I answer myself to close this question.
According to pskink's comment, use asyncMap or concatMap solve my problem. Thanks!!
below is new implementation of testMethod.
asyncMap version:
getItems().asyncMap((item) {
final savedItem = findItemByKey(item.key);
if (savedItem != null)
return savedItem;
else
return Future.value(item);
}).listen(print);
concatMap version:
getItems().concatMap((item) {
final savedItem = findItemByKey(item.key);
if (savedItem != null)
return Observable.fromFuture(savedItem);
else
return Observable.just(item);
}).listen(print);

Related

Existing state editing in Riverpod / Flutter

How I can manipulate the existing state in Riverpod. 'm a beginner about Flutter and Riverpod. When I try add one to Order error pops up and says:
Error: A value of type 'int' can't be assigned to a variable of type
'List'.
final OrderPaperProvider = StateNotifierProvider<OrderPaper, List<Order>>((ref) {
return OrderPaper();
});
#immutable
class Order {
final String product_id;
final String product_name;
final int product_price;
final int product_count;
Order({required this.product_id, required this.product_name, required this.product_price, required this.product_count});
Order copyWith({product_id, product_name, product_price, product_count}) {
return Order(
product_id: product_id,
product_name: product_name,
product_price: product_price,
product_count: product_count,
);
}
}
class OrderPaper extends StateNotifier<List<Order>> {
OrderPaper() : super([]);
void addOrder(Order order) {
for (var x = 0; x < state.length; x++) {
if (state[x].product_id == order.product_id) {
addOneToExistingOrder(x, order);
return;
}
}
state = [...state, order];
}
void removeOrder(String product_id) {
state = [
for (final order in state)
if (order.product_id != order) order,
];
}
void addOneToExistingOrder(index, Order order) {
state = state[index].product_count + 1; // <--------- Error in this line
}
void clearOrderPaper() {
state = [];
}
}
What is happening in the code you posted is basically this:
You are telling it to update the state which is a List<Order> with an integer.
This is because state[index].product_count + 1 actually equals a number, for example 1+2 = 3.
So you are telling it, state = 3, and this causes your error.
What you need to do, is create a new state with the list of items and the edited item, like this (you don't need to pass the index, you can get it in the function):
void addOrder(Order order) {
//find if the product is in the list. The index will not be -1.
final index = state.indexWhere((entry) => entry.product_count == order. product_count);
if (index != -1) {
//if the item is in the list, we just edit the count
state = [
...state.sublist(0, index),
order.copyWith(product_count: state[index].product_count + 1),
...state.sublist(index + 1),
];
}else {
//otherwise, just add it as a new entry.
state = [...state, order],
}
}

Don't execute assignment if value is null

I am still coming up to speed with dart and wanted to know if there was an easier way to not execute a statement if the value is null. See example below:
I can always do the if statements below for setting field3 and field4, but felt like something like field5 should work. But when I try to do that, it complains that a null check operator is used on a null value.
Also I don't want to change the Map to have a dynamic value.
Is there a single one liner to do what I am trying to do, or do I just need to check for null before setting the value.
Map<String, Object> myMap = {};
print('running now');
try {
myMap['field1'] = DummyClass.getString('hello');
myMap['field2'] = DummyClass.getString('good');
//Is there a more concise way to do this than the 2 options below?
if (DummyClass.getOptionalString('goodbye') != null) {
myMap['field3'] = DummyClass.getOptionalString('goodbye')!;
}
String? temp = DummyClass.getOptionalString('go');
if (temp != null) {
myMap['field4'] = temp;
}
// This gives an error 'null check operator used on a null value'
// myMap['field5'] ??= DummyClass.getOptionalString('to')!;
} catch (e) {
print('error condition, $e');
}
print(myMap);
}
class DummyClass {
static String getString(String? strParam) {
String? retString = getOptionalString(strParam);
if (retString == null) {
throw ('nulls are not allowed');
}
return retString;
}
static String? getOptionalString(String? strParam) {
if (strParam == null || strParam.length < 3) {
return null;
}
return strParam;
}
}
There's no built-in way to do what you want, but you could write a function (or extension method) to do it. For example:
extension MapTrySet<K, V> on Map<K, V> {
void trySet(K key, V? value) {
if (value != null) {
this[key] = value;
}
}
}
and then you could do:
myMap.trySet('field3', DummyClass.getOptionalString('goodbye'));
myMap.trySet('field4', DummyClass.getOptionalString('go'));
Alternatively, if you really want to use normal Map syntax, you could create your own Map class that has a void operator []=(K key, V? value) override and does nothing when the value is null, but that probably would not be worth the effort.
The issue is that the ??= operator assigns to the left if it is null. Expanded, it would look something like this:
a ??= b;
// Equivalent to:
if (a == null) {
a = b;
}
Which is not something that you're trying to achieve. AFAIK, there is no such operator yet in Dart. However, you can try this:
final possiblyNullValue = '';
final myMap = <String, String>{};
myMap['key'] = possiblyNullValue ?? myMap['key'];
// Equivalent to:
if (possiblyNullValue != null) {
myMap['key'] = possiblyNullValue;
}
// or:
myMap['key'] = possiblyNullValue != null? possiblyNullValue : myMap['key'];
Which would work in your case as a one-liner.
You could create your map with all entries, even null, and then filter the null values out:
void main() {
try {
final myMap = <String, dynamic>{
'field1': DummyClass.getString('hello'),
'field2': DummyClass.getString('good'),
'field3': DummyClass.getOptionalString('goodbye'),
'field4': DummyClass.getOptionalString('go'),
}..removeWhere((k, v) => v == null);
print(myMap);
} catch (e) {
print('error condition, $e');
}
}

HERE API Autosuggest Geocoding search

I am looking to use the HERE Geocoding Autosuggest. I understand how the API works and it is the implementation in Flutter I seek guidance on.
There is a Javascript example for the previous version
https://developer.here.com/documentation/examples/rest/geocoding_suggestions
This demonstrates the call and Json return, but I wondered if there were any Flutter examples/ guidance on implementation when it comes to displaying the data.
For example, the API returns address results for 'London', does Flutter have build in functionality to display these to the user (Such as TypeAheadField), in a dropdown style box below entry field for example, like the HERE screenshot below, where the user can select the correct suggestion? How would the call be implemented with this function?
I presume I will utilise an onChanged/SetState style function to call and display, but it is how to make the call as user types and then display the returned suggestion that I would find an example useful.
Any resources/ tips welcome
Thank you
Please check the below code ,which explains the use of auto suggest in the flutter.
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:here_sdk/core.dart';
import 'package:here_sdk/core.errors.dart';
import 'package:here_sdk/gestures.dart';
import 'package:here_sdk/mapview.dart';
import 'package:here_sdk/search.dart';
import 'SearchResultMetadata.dart';
// A callback to notify the hosting widget.
typedef ShowDialogFunction = void Function(String title, String message);
class SearchExample {
HereMapController _hereMapController;
MapCamera _camera;
MapImage? _poiMapImage;
List<MapMarker> _mapMarkerList = [];
late SearchEngine _onlineSearchEngine;
late OfflineSearchEngine _offlineSearchEngine;
bool useOnlineSearchEngine = true;
ShowDialogFunction _showDialog;
SearchExample(ShowDialogFunction showDialogCallback, HereMapController hereMapController)
: _showDialog = showDialogCallback,
_hereMapController = hereMapController,
_camera = hereMapController.camera {
double distanceToEarthInMeters = 5000;
MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters);
_camera.lookAtPointWithMeasure(GeoCoordinates(52.520798, 13.409408), mapMeasureZoom);
try {
_onlineSearchEngine = SearchEngine();
} on InstantiationException {
throw ("Initialization of SearchEngine failed.");
}
try {
// Allows to search on already downloaded or cached map data.
_offlineSearchEngine = OfflineSearchEngine();
} on InstantiationException {
throw ("Initialization of OfflineSearchEngine failed.");
}
_setTapGestureHandler();
_setLongPressGestureHandler();
_showDialog("Note", "Long press on the map to get the address for that location with reverse geocoding.");
}
Future<void> searchButtonClicked() async {
// Search for "Pizza" and show the results on the map.
_searchExample();
// Search for auto suggestions and log the results to the console.
_autoSuggestExample();
}
Future<void> geocodeAnAddressButtonClicked() async {
// Search for the location that belongs to an address and show it on the map.
_geocodeAnAddress();
}
void useOnlineSearchEngineButtonClicked() {
useOnlineSearchEngine = true;
_showDialog('Switched to SearchEngine', 'Requests will be calculated online.');
}
void useOfflineSearchEngineButtonClicked() {
useOnlineSearchEngine = false;
// Note that this app does not show how to download offline maps. For this, check the offline_maps_app example.
_showDialog(
'Switched to OfflineSearchEngine', 'Requests will be calculated offline on cached or downloaded map data.');
}
void _searchExample() {
String searchTerm = "Pizza";
print("Searching in viewport for: " + searchTerm);
_searchInViewport(searchTerm);
}
void _geocodeAnAddress() {
// Set map to expected location.
GeoCoordinates geoCoordinates = GeoCoordinates(52.53086, 13.38469);
double distanceToEarthInMeters = 1000 * 5;
MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters);
_camera.lookAtPointWithMeasure(geoCoordinates, mapMeasureZoom);
String queryString = "Invalidenstraße 116, Berlin";
print("Finding locations for: $queryString. Tap marker to see the coordinates.");
_geocodeAddressAtLocation(queryString, geoCoordinates);
}
void _setTapGestureHandler() {
_hereMapController.gestures.tapListener = TapListener((Point2D touchPoint) {
_pickMapMarker(touchPoint);
});
}
void _setLongPressGestureHandler() {
_hereMapController.gestures.longPressListener = LongPressListener((GestureState gestureState, Point2D touchPoint) {
if (gestureState == GestureState.begin) {
GeoCoordinates? geoCoordinates = _hereMapController.viewToGeoCoordinates(touchPoint);
if (geoCoordinates == null) {
return;
}
_addPoiMapMarker(geoCoordinates);
_getAddressForCoordinates(geoCoordinates);
}
});
}
Future<void> _getAddressForCoordinates(GeoCoordinates geoCoordinates) async {
SearchOptions reverseGeocodingOptions = SearchOptions.withDefaults();
reverseGeocodingOptions.languageCode = LanguageCode.enGb;
reverseGeocodingOptions.maxItems = 1;
if (useOnlineSearchEngine) {
_onlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
(SearchError? searchError, List<Place>? list) async {
_handleReverseGeocodingResults(searchError, list);
});
} else {
_offlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
(SearchError? searchError, List<Place>? list) async {
_handleReverseGeocodingResults(searchError, list);
});
}
}
// Note that this can be called by the online or offline search engine.
void _handleReverseGeocodingResults(SearchError? searchError, List<Place>? list) {
if (searchError != null) {
_showDialog("Reverse geocoding", "Error: " + searchError.toString());
return;
}
// If error is null, list is guaranteed to be not empty.
_showDialog("Reverse geocoded address:", list!.first.address.addressText);
}
void _pickMapMarker(Point2D touchPoint) {
double radiusInPixel = 2;
_hereMapController.pickMapItems(touchPoint, radiusInPixel, (pickMapItemsResult) {
if (pickMapItemsResult == null) {
// Pick operation failed.
return;
}
List<MapMarker>? mapMarkerList = pickMapItemsResult.markers;
if (mapMarkerList.length == 0) {
print("No map markers found.");
return;
}
MapMarker topmostMapMarker = mapMarkerList.first;
Metadata? metadata = topmostMapMarker.metadata;
if (metadata != null) {
CustomMetadataValue? customMetadataValue = metadata.getCustomValue("key_search_result");
if (customMetadataValue != null) {
SearchResultMetadata searchResultMetadata = customMetadataValue as SearchResultMetadata;
String title = searchResultMetadata.searchResult.title;
String vicinity = searchResultMetadata.searchResult.address.addressText;
_showDialog("Picked Search Result", title + ". Vicinity: " + vicinity);
return;
}
}
double lat = topmostMapMarker.coordinates.latitude;
double lon = topmostMapMarker.coordinates.longitude;
_showDialog("Picked Map Marker", "Geographic coordinates: $lat, $lon.");
});
}
Future<void> _searchInViewport(String queryString) async {
_clearMap();
GeoBox viewportGeoBox = _getMapViewGeoBox();
TextQueryArea queryArea = TextQueryArea.withBox(viewportGeoBox);
TextQuery query = TextQuery.withArea(queryString, queryArea);
SearchOptions searchOptions = SearchOptions.withDefaults();
searchOptions.languageCode = LanguageCode.enUs;
searchOptions.maxItems = 30;
if (useOnlineSearchEngine) {
_onlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
_handleSearchResults(searchError, list, queryString);
});
} else {
_offlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
_handleSearchResults(searchError, list, queryString);
});
}
}
// Note that this can be called by the online or offline search engine.
void _handleSearchResults(SearchError? searchError, List<Place>? list, String queryString) {
if (searchError != null) {
// Note: When using the OfflineSearchEngine, the HERE SDK searches only on cached map data and
// search results may not be available for all zoom levels.
// Please also note that it may take time until the required map data is loaded.
// Subsequently, the cache is filled when a user pans and zooms the map.
_showDialog("Search", "Error: " + searchError.toString());
return;
}
// If error is null, list is guaranteed to be not empty.
int listLength = list!.length;
_showDialog("Search for $queryString", "Results: $listLength. Tap marker to see details.");
// Add new marker for each search result on map.
for (Place searchResult in list) {
Metadata metadata = Metadata();
metadata.setCustomValue("key_search_result", SearchResultMetadata(searchResult));
// Note: getGeoCoordinates() may return null only for Suggestions.
_addPoiMapMarkerWithMetadata(searchResult.geoCoordinates!, metadata);
}
}
Future<void> _autoSuggestExample() async {
GeoCoordinates centerGeoCoordinates = _getMapViewCenter();
SearchOptions searchOptions = SearchOptions.withDefaults();
searchOptions.languageCode = LanguageCode.enUs;
searchOptions.maxItems = 5;
TextQueryArea queryArea = TextQueryArea.withCenter(centerGeoCoordinates);
if (useOnlineSearchEngine) {
// Simulate a user typing a search term.
_onlineSearchEngine.suggest(
TextQuery.withArea(
"p", // User typed "p".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
_onlineSearchEngine.suggest(
TextQuery.withArea(
"pi", // User typed "pi".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
_onlineSearchEngine.suggest(
TextQuery.withArea(
"piz", // User typed "piz".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
} else {
// Simulate a user typing a search term.
_offlineSearchEngine.suggest(
TextQuery.withArea(
"p", // User typed "p".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
_offlineSearchEngine.suggest(
TextQuery.withArea(
"pi", // User typed "pi".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
_offlineSearchEngine.suggest(
TextQuery.withArea(
"piz", // User typed "piz".
queryArea),
searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
_handleSuggestionResults(searchError, list);
});
}
}
void _handleSuggestionResults(SearchError? searchError, List<Suggestion>? list) {
if (searchError != null) {
print("Autosuggest Error: " + searchError.toString());
return;
}
// If error is null, list is guaranteed to be not empty.
int listLength = list!.length;
print("Autosuggest results: $listLength.");
for (Suggestion autosuggestResult in list) {
String addressText = "Not a place.";
Place? place = autosuggestResult.place;
if (place != null) {
addressText = place.address.addressText;
}
print("Autosuggest result: " + autosuggestResult.title + " addressText: " + addressText);
}
}
Future<void> _geocodeAddressAtLocation(String queryString, GeoCoordinates geoCoordinates) async {
_clearMap();
AddressQuery query = AddressQuery.withAreaCenter(queryString, geoCoordinates);
SearchOptions geocodingOptions = SearchOptions.withDefaults();
geocodingOptions.languageCode = LanguageCode.deDe;
geocodingOptions.maxItems = 30;
if (useOnlineSearchEngine) {
_onlineSearchEngine.searchByAddress(query, geocodingOptions, (SearchError? searchError, List<Place>? list) async {
_handleGeocodingResults(searchError, list, queryString);
});
} else {
_offlineSearchEngine.searchByAddress(query, geocodingOptions,
(SearchError? searchError, List<Place>? list) async {
_handleGeocodingResults(searchError, list, queryString);
});
}
}
// Note that this can be called by the online or offline search engine.
void _handleGeocodingResults(SearchError? searchError, List<Place>? list, String queryString) {
if (searchError != null) {
_showDialog("Geocoding", "Error: " + searchError.toString());
return;
}
String locationDetails = "";
// If error is null, list is guaranteed to be not empty.
for (Place geocodingResult in list!) {
// Note: getGeoCoordinates() may return null only for Suggestions.
GeoCoordinates geoCoordinates = geocodingResult.geoCoordinates!;
Address address = geocodingResult.address;
locationDetails = address.addressText +
". GeoCoordinates: " +
geoCoordinates.latitude.toString() +
", " +
geoCoordinates.longitude.toString();
print("GeocodingResult: " + locationDetails);
_addPoiMapMarker(geoCoordinates);
}
int itemsCount = list.length;
_showDialog("Geocoding result for $queryString. Results: $itemsCount", locationDetails);
}
Future<MapMarker> _addPoiMapMarker(GeoCoordinates geoCoordinates) async {
// Reuse existing MapImage for new map markers.
if (_poiMapImage == null) {
Uint8List imagePixelData = await _loadFileAsUint8List('poi.png');
_poiMapImage = MapImage.withPixelDataAndImageFormat(imagePixelData, ImageFormat.png);
}
MapMarker mapMarker = MapMarker(geoCoordinates, _poiMapImage!);
_hereMapController.mapScene.addMapMarker(mapMarker);
_mapMarkerList.add(mapMarker);
return mapMarker;
}
Future<Uint8List> _loadFileAsUint8List(String fileName) async {
// The path refers to the assets directory as specified in pubspec.yaml.
ByteData fileData = await rootBundle.load('assets/' + fileName);
return Uint8List.view(fileData.buffer);
}
Future<void> _addPoiMapMarkerWithMetadata(GeoCoordinates geoCoordinates, Metadata metadata) async {
MapMarker mapMarker = await _addPoiMapMarker(geoCoordinates);
mapMarker.metadata = metadata;
}
GeoCoordinates _getMapViewCenter() {
return _camera.state.targetCoordinates;
}
GeoBox _getMapViewGeoBox() {
GeoBox? geoBox = _camera.boundingBox;
if (geoBox == null) {
print(
"GeoBox creation failed, corners are null. This can happen when the map is tilted. Falling back to a fixed box.");
GeoCoordinates southWestCorner = GeoCoordinates(
_camera.state.targetCoordinates.latitude - 0.05, _camera.state.targetCoordinates.longitude - 0.05);
GeoCoordinates northEastCorner = GeoCoordinates(
_camera.state.targetCoordinates.latitude + 0.05, _camera.state.targetCoordinates.longitude + 0.05);
geoBox = GeoBox(southWestCorner, northEastCorner);
}
return geoBox;
}
void _clearMap() {
_mapMarkerList.forEach((mapMarker) {
_hereMapController.mapScene.removeMapMarker(mapMarker);
});
_mapMarkerList.clear();
}
}
For more details please check enter link description here

My async metho didn't go after "for" iteration

My code like this:
Future<List<ListClass>> getIndexList() async {
return Future.delayed(delayTime).then((_) async {
//initialize
List<ListClass> resultListItems = new List<ListClass>();
await listCollection.get().then((value) async {
var v = value.data;
for (var data in v) {
String userId = data['userId'];
String authorName=await UserTable().getUserNameById(userId);
print("createUserName=" + authorName);
resultListItems.add(
ListClass(header, content, userId, wordCount, authorName));
}
print("resultListItems.length="+resultListItems.length.toString());
return resultListItems;
});
return resultListItems;
});
}
When I debug,it shows that this method return null,and after the for,the print("resultListItems"); doesn't run too. How can I fix this?Thanks!!
I have found the problem,the for clause doesn't run completely.One of my data in database is null,so it runs with bug.Sorry for my fault

Check whether a list contain an attribute of an object in dart

I need to check whether myItemsList contains myitem.itemId or not, If it exists need to add itemQuantity, if it not exists need to add myitem object to myItemsList.
List<MyItem> myItemsList = new List();
MyItem myitem = new MyItem (
itemId: id,
itemName: name,
itemQuantity: qty,
);
if (myItemsList.contains(myitem.itemId)) {
print('Already exists!');
} else {
print('Added!');
setState(() {
myItemsList.add(myitem);
});
}
MyItem class
class MyItem {
final String itemId;
final String itemName;
int itemQuantity;
MyItem ({
this.itemId,
this.itemName,
this.itemQuantity,
});
}
above code is not working as expected, please help me to figure out the issue.
Contains() compares the whole objects.
Besides overriding == operator or looping over, you can use list's singleWhere method:
if ((myItemsList.singleWhere((it) => it.itemId == myitem.itemId,
orElse: () => null)) != null) {
Edit:
As Dharaneshvar experienced and YoApps mentioned in the comments .singleWhere raises StateError when more elements are found.
This is desired when you expect unique elements such as in the case of comparing IDs.
Raised error is the friend here as it shows that there is something wrong with the data.
For other cases .firstWhere() is the right tool:
if ((myItemsList.firstWhere((it) => it.itemName == myitem.itemName,
orElse: () => null)) != null) {
// EO Edit
Whole example:
List<MyItem> myItemsList = new List();
​
class MyItem {
final String itemId;
final String itemName;
int itemQuantity;
​
MyItem({
this.itemId,
this.itemName,
this.itemQuantity,
});
}
​
void main() {
MyItem myitem = new MyItem(
itemId: "id00",
itemName: "name",
itemQuantity: 50,
);
​
myItemsList.add(myitem);
​
String idToCheck = "id00";
​
if ((myItemsList.singleWhere((it) => it.itemId == idToCheck,
orElse: () => null)) != null) {
print('Already exists!');
} else {
print('Added!');
}
}
As already said before, contains compares two Objects with the == operator. So you currently compare MyItem with String itemId, which will never be the same.
To check whether myItemsList contains myitem.itemId you can use one of the following:
myItemsList.map((item) => item.itemId).contains(myitem.itemId);
or
myItemsList.any((item) => item.itemId == myitem.itemId);
You're using contains slightly wrong.
From: https://api.dartlang.org/stable/2.2.0/dart-core/Iterable/contains.html
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}
You can either override the == operator, see: https://dart-lang.github.io/linter/lints/hash_and_equals.html
#override
bool operator ==(Object other) => other is Better && other.value == value;
Or you can loop over your list and search the normal way one by one, which seems slightly easier.
One more way to check does list contain object with property or not
if (myList.firstWhereOrNull((val) => val.id == someItem.id) != null) {}