Warning: Operand of null-aware operation '??' has type 'int' which excludes null - flutter

Warning: Operand of null-aware operation '??' has type 'int' which excludes null. _countries.indexWhere((country)
onTap: () {
int index =
_countries.indexWhere((country) {
return country.startsWith(
alphabet.toUpperCase());
}) ??
0;
_listController.jumpTo(
index * 60.0,
);
},
child: Text(
alphabet,
style: TextStyle(
color: _theme.primaryColor,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
),

According to documentation, List.indexWhere always returns int - if the element isn't found, the return value is -1, but you seem to be thinking that it's null.

The documentation on indexWhere clearly states:
Returns -1 if element is not found.
So there is no possible way that your call returns null. The ?? operator only works on a nullable variable/expression, because it will return the result, or (in your case) 0 if the result is null. The result can never be null so your compiler tells you that that statement does not make any sense.
If you wanted the -1 to also be 0, you could use min to make sure the minimum you get is always 0.

indexWhere doesn't return nullable int. You might want firstWhere and then find index.
String item = _countries.firstWhere((country) {
return country.startsWith(alphabet.toUpperCase());
}, orElse: () => _countries.first);
int index = _countries.indexWhere((element) => element == item);
int selectedIndex = 0;
for (int i = 0; i < _countries.length; i++) {
if (_countries[i].startsWith(alphabet.toUpperCase())) {
selectedIndex = i;
break;
}
}
I hope there are better ways of doing it.

Related

How can I gather and show results of a survey made with survey_kit package in Flutter?

I am struggling in retrieving the results obtained from a survey built with survey_kit package. A SurveyResult object is supposed to contain a list of StepResults and the FinishReason. The StepResult contains a list of QuestionResults. I cannot access the StepResult in anyway.
Example proposed in the documentation:
SurveyKit
(
onResult: (SurveyResult result) {
//Read finish reason from result (result.finishReason)
//and evaluate the results }
)
I already tried to tap something like result.stepResult but no variable was suggested.
I'm not sure if its the best approach but after looking into SurveyKit I've found that the SurveyResult class holds a list of StepResult and each of them holds a list of QuestionResult which in turn holds a value field called valueIdentifier.
so you can Iterate over them and extract the values. but first, you need to ensure that all of your answers have value. for example:
answerFormat: const SingleChoiceAnswerFormat(
textChoices: [
TextChoice(text: 'option 1', value: '10'),
TextChoice(text: 'option 2', value: '-2'),
]
),
Then after you did that iterate over them like that:
onResult: (SurveyResult result) {
int score = 0;
for (var stepResult in result.results) {
for (var questionResultin stepResult.results) {
score += int.tryParse(questionResult.valueIdentifier ?? "0") ?? 0;
}
}
print("final Score is $score");
/* call a new widget to show the results*/
},
As you can see I use two null checks when adding a question value to the score.
The first one is because the value is of type "String?" (and not "String") and the second one is because the String value might be non-numeric.
Of course, after you have calculated the results you can show the result on a new screen with Navigator.

Map getter not pulling items by index properly

I have a Map of <String, CartItem> which is a custom class, and I am trying to return specific values from that Map, but every time I do return them in the format item[I], I get a "Null check operator used on a null value." Is there a different way I should be calling this?
Details
I have a map of _items with a public getter that returns those items:
class Cart with ChangeNotifier {
Map<String, CartItem> _items = {};
Map<String, CartItem> get items {
return {..._items};
}
Followed by a function that adds new items to the Map:
void addItem(
String productId,
double price,
String title,
) {
if (_items.containsKey(productId)) {
_items.update(
productId,
(existingCartItem) => CartItem(
id: existingCartItem.id,
title: existingCartItem.title,
price: existingCartItem.price,
quantity: (existingCartItem.quantity + 1),
),
);
} else {
_items.putIfAbsent(
productId,
() => CartItem(
id: DateTime.now().toString(),
title: title,
price: price,
quantity: 1,
),
);
}
print(items.length);
print(items[0]);
print(items);
notifyListeners();
}
When I call addItem, this is the output I get from those three print statements - it appears calling as items[0] returns null, even though the length and the full items list print properly:
Performing hot restart...
Restarted application in 1,483ms.
flutter: 1
flutter: null
flutter: {p1: Instance of 'CartItem'}
Then whenever I call that Cart Provider looking for a specific item in the Map:
child: ListView.builder(
itemCount: cart.itemCount,
itemBuilder: (ctx, i) => CartItem(cart.items[i]!)),
)
I get a "Null check operator used on a null value" error. Why is this way of calling the items in the map returning null?
You seem to assume that items[0] works like an array and returns the first element. It does not. A Map has an indexer by key. It returns the item, with the given key. That is the whole point of a map, being able to look up items by key. You set your productId as a key, so to find it you would need to use items[productId].
Some thoughts: does your cart items needs to be a map? If all you want is enumerating through it, it would work if you made it a simple list instead. Then the numeric indexer would work again.
If it needs to be a map, you can use items.values to iterate through all the values. But please note that a map is not ordered. Again, if you need an ordered list, it would be better to use a list in the first place.

How to sort a list that could contain null values with dart null-safety

I have a list of strings that may contain null values, how do I sort this list?
I'm using Flutter beta channel so null-safety is checked. This is what I have so far:
List<String?> _list = [
'beta',
'fotxtrot',
'alpha',
null,
null,
'delta',
];
_list.sort((a, b) => a!.compareTo(b!));
How do I get this as the outcome:
_list = [
null,
null,
'alpha',
'beta',
'delta',
'fotxtrot',
];
I encountered this recently and built a one line function based on compareTo documentation:
myList.sort((a, b) => a==null ? 1: b==null? -1 : a.compareTo(b));
NB: This brings the null value at the end of the list. In your case just swap -1 and 1 to have them at the front of your List.
You need to modify your sorting method to handle nullable values, not just ignore them. After handling potential nulls you can compare them normally.
_list.sort((a, b) {
if(a == null) {
return -1;
}
if(b == null) {
return 1;
}
return a.compareTo(b);
});
You could also use whereType:
List<String?> _list = [
'c',
'a',
'd',
null,
null,
'b',
];
void main() {
var list = _list.whereType<String>().toList();
list.sort();
print(list); // [a, b, c, d]
}

How to check for decimal number

I have a schema:
const SignupSchema = Yup.object().shape({
decimal: Yup.number().integer('invalid decimal'),
});
I need to check if the number is a decimal, but I found only Integer in docs.
You can add a custom validation test e.g. with regex.
const SignupSchema = Yup.object().shape({
decimal: Yup.number().test(
'is-decimal',
'invalid decimal',
value => (value + "").match(/^\d*\.{1}\d*$/),
),
});
const digitsOnly = (value: string) => /^\d*[\.{1}\d*]\d*$/.test(value) || value.length === 0
const schema = yup.object().shape({
inputEntry: yup
.string()
.test('inputEntry', 'The field should have digits only', digitsOnly)
});
Above code is used for allowing only decimal,whole and null values in the input field.
just keep yup.number for decimals

Drools Accumulate on Properties

I have inherited some Drools code and am trying to understand exactly how it is working.
The code in question should go through a number of dates from two different sources, and for one source find the earliest and the other source find the latest.
The code is:
when
$flags: Properties()
// these properties contain key/value pairs with dates (as Strings)
$root: Map()
Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
$someRequestMap: Map() from $someRequestValue
// this map contains some timestamps as Strings
$earliestTimestamp: String() from accumulate(
$value : String(),
init( String found = null; ),
action( found = found == null? $value : ($value.compareTo(found) < 0? $value: found); ),
result( found )
)
$latestTimestamp: String() from accumulate(
$value : String(),
init( String found = null; ),
action( found = found == null? $value : ($value.compareTo(found) > 0? $value: found); ),
result( found )
)
then
log("earliestTimestamp: {}", $earliestTimestamp);
String latestDate = (String) $flags.get($latestTimestamp);
log("latestDate: {}", latestDate);
end
The $flags Properties are populated as so:
when
$flags: Properties()
$root: Map()
Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
$someRequestMap: Map() from $someRequestValue
Map.Entry( key == "timestamp", $timestampValue: value) from $someRequestMap.entrySet()
Map.Entry( key == "data", $dataValue: value) from $someRequestMap.entrySet()
$data: Map() from $dataValue
Map.Entry( key == "simple", $simpleValue: value) from $data.entrySet()
$simple: Map() from $simpleValue
Map.Entry( key == "somedate", $somedateValue: value) from $simple.entrySet()
then
$someRequestMap.remove("data");
update($root);
$flags.put($timestampValue, $somedateValue);
insert ($timestampValue);
end
And the JSON which is input to the rules is as so (with the timestamp strings):
{
"someRequest": {
"data": {
"simple": {
"somedate": "13-01-2016",
}
},
"timestamp": "2016-01-01 12:34:56.789"
}
}
I can see that it gets all the String facts available in working memory to get earliestTimestamp.
I think that for latestTimestamp, since it is called in the RHS on $flags.get, it is actually finding all Strings in $flags.
However if I insert log outputs inside the two accumulate action sections, all I see is the timestamp strings from working memory (I don't see the $flags strings).
I am comfortable enough using Drools but this bit of code has confused me in terms of how it works with the Properties.
Any info appreciated, thanks.