Every time I run my app. It shows
"Null check operator used on a null value".
I have shown some solutions but couldn't successfully apply them to my code. How do I solve this?
import 'dart:math';
class bmicalculator {
bmicalculator({required this.height, required this.weight});
int height;
double weight;
double? bmi;
String Calculation() {
bmi = weight / pow(height / 100, 2);
return bmi!.toStringAsFixed(2);
}
String getResult() {
if (bmi! >= 25) {
return 'Overweight';
} else if (bmi! > 18.5) {
return 'Normal';
} else
return 'UnderWeight';
}
String getInterpretation() {
if (bmi! >= 25) {
return 'String 1';
} else if (bmi! > 18.5) {
return 'String 2';
} else
return 'String 3';
}
}
The null check operator(!) is used at getResult() and getInterpretation() functions. This operator should NOT be used if the value can be null. The bmi value can be null, so you don't use the ! operator if that can be null.
Solution
Add condition before using the bmi value like below.
String getResult() {
if (bmi == null)
throw Exception(); // or return 'The bmi is null!';
if (bmi! >= 25) {
return 'Overweight';
} else if (bmi! > 18.5) {
return 'Normal';
} else
return 'UnderWeight';
}
this would happen when you call getResult or getInterpretation without calling Calculation previously, and the problem is that you are not initilizing the value of bmi which is a String? type and it's initial value is null, so when you try to use one of the methods getResult or getInterpretation you would get error because bmi is null,
you can solve the issue by initializing the bmi value in the constructor like:
bmicalculator({required this.height, required this.weight}){
bmi = weight / pow(height / 100, 2);
}
Related
I am not getting why / operator is giving me this error. plz someone help me with it
FYI i am making a BMI calculator app with refernce to Angela Yu's course on Udemy.
import 'dart:math';
class CalculatorBrain {
CalculatorBrain({this.height, this.weight});
final int? height;
final int? weight;
double _bmi = 0;
String calculateBMI() {
_bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
String getResults() {
if (_bmi >= 25)
return 'Overweight';
else if (_bmi > 18.5)
return 'Normal';
else
return 'Underweight';
}
String getInterpretation() {
if (_bmi >= 25)
return 'You have a higher than normal body weigth. Try to exercise more.';
else if (_bmi > 18.5)
return 'You have a normal body weight. Good job!';
else
return 'You have a lower than normal body weight. You can eat a bit more.';
}
}
your efforts will be appreciated
You have to find a good fallback in case height or wight is null. One way to do this is using the ?? operator.
This is how you can fallback to 0 in both cases, which would cause more errors because you then would divide by 0.
_bmi = (weight ?? 0) / pow((height ?? 0) / 100, 2);
Better, set _bmi to a specific value when one or both values are missing.
double _bmi = 0;
String calculateBMI() {
// always set it to 0 first in case values are missing
_bmi = 0;
if (height != null && weight != null) {
_bmi = weight! / pow(height! / 100, 2);
}
return _bmi.toStringAsFixed(1);
}
The answer by #passsy is technically right but I'm wondering why you declared height and weight as nullable. You could rewrite your class as below by making the 2 parameters required (and thus making sure they cannot be null):
class CalculatorBrain {
CalculatorBrain({required this.height, required this.weight});
final int height;
final int weight;
double _bmi = 0;
String calculateBMI() {
_bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
here the code
all operator can't be invoked because the receiver cab be 'null'
class Bmicalculator {
final height;
final weight;
double? _bmi;
Bmicalculator({this.height, this.weight});
String calculateBmi() {
double _bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
String getResult() {
if (_bmi >= 25) {
return 'overweight';
} else if (_bmi >= 18.5) {
return 'Normal';
} else {
return 'underWeight';
}
}
please solve the essue
use null safe !
String getResult() {
if (_bmi! >= 25) { // here need to change
return 'overweight';
} else if (_bmi! >= 18.5) {// here need to change
return 'Normal';
} else {
return 'underWeight';
}
}
On your class level, _bmi is nullable double double? _bmi;.
you can do it like
String getResult() {
if(_bmi==null){
return "got null on BMI";
}
else if (_bmi! >= 25) {
return 'overweight';
} else if (_bmi! >= 18.5) {
return 'Normal';
} else {
return 'underWeight';
}
}
! is use If you know that an expression never evaluates to null.
Learn more about null-safety
import 'dart:math';
class CalcuatorBrain {
CalcuatorBrain({this.height, this.weight});
final int? height;
final int? weight;
final double _bmi = 0;
String calculateBMI() {
double _bmi = weight! / pow(height! / 100, 2);
//double _bmi = weight! / (height! * height! ) / 100;
return _bmi.toStringAsFixed(1);
}
String getResult() {
if (_bmi >= 25) {
return 'Overweight';
} else if (_bmi < 18.5) {
return 'Normal';
} else {
return 'Underweight';
}
}
String getInterpretation() {
if (_bmi >= 25) {
return 'Try to exercise more.';
} else if (_bmi >= 18.5) {
return 'Good job,';
} else {
return 'You can eat a bit more.';
}
}
}
I can't understand what's wrong with my code. The original code works fine (https://github.com/londonappbrewery/BMI-Calculator-Flutter-Completed) but it's outdated, mine has some null checks with "int?" and I also was forced to make:
double _bmi = weight! / pow(height! / 100, 2);
by adding "!" 2 times.Still I get the same 'Underweight' and 'You can eat a bit more.' but BMI is different. What's the problem?
There is a typo in code. In getResult,
} else if (_bmi < 18.5) { needs to be
} else if (_bmi >= 18.5) {.
Also prefer non nullable types. I looked the original code, height and weight has default values. So we can make them non-nullable.
_bmi should be computed in constructor. Because if getResult called before calculateBMI, it will return Underweight as _bmi is 0. If it is computed in constructor, we can call any method in any order.
import 'dart:math';
class CalculatorBrain {
CalculatorBrain({
required this.height,
required this.weight,
}) : _bmi = weight / pow(height / 100, 2);
final int height;
final int weight;
final double _bmi;
String calculateBMI() {
return _bmi.toStringAsFixed(1);
}
String getResult() {
if (_bmi >= 25) {
return 'Overweight';
} else if (_bmi >= 18.5) {
return 'Normal';
} else {
return 'Underweight';
}
}
String getInterpretation() {
if (_bmi >= 25) {
return 'Try to exercise more.';
} else if (_bmi >= 18.5) {
return 'Good job.';
} else {
return 'You can eat a bit more.';
}
}
}
Let's examine your code:
final double _bmi = 0;
String calculateBMI() {
double _bmi = weight! / pow(height! / 100, 2);
// double _bmi = weight! / (height! * height! ) / 100;
return _bmi.toStringAsFixed(1);
}
String getInterpretation() {
if (_bmi >= 25) {
return 'Try to exercise more.';
} else if (_bmi >= 18.5) {
return 'Good job,';
} else {
return 'You can eat a bit more.';
}
}
The _bmi property is always 0.
In the calculateBMI method a local variable _bmi gets calculated which shadows the _bmi property.
The getInterpretation method doesn't use the result from the calculateBMI method but always uses the final property value.
Let's examine the original code:
double _bmi;
String calculateBMI() {
_bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
String getInterpretation() {
if (_bmi >= 25) {
return 'You have a higher than normal body weight. Try to exercise more.';
} else if (_bmi >= 18.5) {
return 'You have a normal body weight. Good job!';
} else {
return 'You have a lower than normal body weight. You can eat a bit more.';
}
}
The _bmi property can be modified.
Besides returning a string representation of the calculated BMI, the calculateBMI method updates the _bmi property.
The getInterpretation method uses that updated value, if the calculateBMI method is called before.
Conclusion
As far as I can see, your problem has nothing to do with the update towards non-nullable types. Rather, you should update the property instead of shadowing it with a local variable.
References
Final and const | dart.dev
How do getters and setters change properties in Dart? | stackoverflow.com
Variable shadowing | wikipedia.org
I just finished my nullsafe migration. I'm finding that wrapping code with a null check only sometimes removes the need for the nullcheck ! operator? E.g.,
class MyClass {
double divideBy4(double numerator) {
return numerator / 4;
}
double quarteredWorks(double? value) {
if (value != null)
return divideBy4(value); // <- no intellisense warning
else
return 0;
}
double quarteredDoesntWork(double? value) {
return divideBy4(value); // <- intellisense: "double? can't be assigned to double"
}
double? value;
double divideBy2() {
if (value != null)
return value / 2; // <- intellisense: "receiver can be null"
else
return .0;
}
}
EDIT
Changed my example to show an example of wrapping with a null check that works
I made an app and I create a simple logic. But when I run it it throws me
The method '>' was called on null.
Receiver: null
Tried calling: >(25)
I mean is a basic math comparison, I don't know why it throws me that, here's my file
import 'dart:math';
class CalculatorBrain {
CalculatorBrain({this.height, this.weight});
final int height;
final int weight;
double _bmi;
String calculateBMI() {
double _bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
String getResult() {
if (_bmi >= 25) {
return 'Overweight';
} else if (_bmi > 18.5) {
return 'Normal';
} else {
return 'Underweight';
}
}
String getInterpretation() {
if (_bmi >= 25) {
return 'You have a higher than normal body weight. Try to exercise more';
} else if (_bmi > 18.5) {
return 'You have a normal body weight. Good job!';
} else {
return 'You have aa lower than normal body weight. You can eat a bit more.';
}
}
}
Can you help me understand this error?
In calculateBMI() you declare new local variable _bmi by declaring its type, so _bmi field of class CalculatorBrain is still null. Just remove type declaration of _bmi variable in calculateBMI().
You can also change calculateBMI() into getter and remove _bmi field completely. And mark height and weight as a required. Also you can add assertions to make sure this values is greater than 0 and are not null.
import 'dart:math';
import 'meta';
class CalculatorBrain {
CalculatorBrain({#required this.height,
#required this.weight,
}) : assert(height > 0), assert(weight > 0);
final int height;
final int weight;
double get _bmi => weight / pow(height / 100, 2);
String getResult() {
if (_bmi >= 25) {
return 'Overweight';
} else if (_bmi > 18.5) {
return 'Normal';
} else {
return 'Underweight';
}
}
String getInterpretation() {
if (_bmi >= 25) {
return 'You have a higher than normal body weight. Try to exercise more';
} else if (_bmi > 18.5) {
return 'You have a normal body weight. Good job!';
} else {
return 'You have aa lower than normal body weight. You can eat a bit more.';
}
}
}
Probably you are calling getResult() or getInterpretation() before asigning a value to _bmi.
To prevent this, you might want to check if _bmi is null before comparing it. Here is an example for your getResult function:
String getResult() {
if (_ bmi != null){
if (_bmi >= 25) {
return 'Overweight';
} else if (_bmi > 18.5) {
return 'Normal';
} else {
return 'Underweight';
}
}
}