I have a final and I am trying initializing that in the constructor. It is giving me error & If I don't make it final I get a warning.
This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: GenderCard.genderSvg",
My Code:
GenderCard({#required this.genderType}) {
genderSvg = '/assets/' + 'genderType' + '.svg';
}
final String genderType;
final String genderSvg;
#override
Widget build(BuildContext context) {
final instance variables must be initialized in the initializer list. See the language guide.
Instance variables can be final but not const. Final instance
variables must be initialized before the constructor body starts — at
the variable declaration, by a constructor parameter, or in the
constructor’s initializer list.
Change your constructor to:
class GenderCard {
GenderCard({#required this.genderType})
: genderSvg = '/assets/$genderType.svg';
final String genderType;
final String genderSvg;
}
Related
I wanna know how can I create an instance of an Object from the passed generic Type T passed from the super class constructor
this example of what I want to achieve but it's wrong :
class Widget<T> extends StatelessWidget {
Widget({super.key});
final T instanceOfT = T(); // throws 'T' isn't a function.
#override
Widget build(BuildContext context) {
return Text(instanceOfT.exampleStringProperty);
}
}
class ExampleClass {
final String exampleStringProperty;
const ExampleClass({this.exampleStringProperty = "exampleValue"});
}
I'm expecting that I should pass the Type from the generic call when calling the Widget constructor like this:
Widget<ExampleClass>(),
Then an instance of the ExampleClass should be created and works fine.
Any ideas on this ?
I'm having a hard-time understanding the structure of dart objects. Can someone explain what is the rightway to structure dart objects?
In the first code snippet, the constructor is called before the initiation of the variables with a final tag.
class _VideoDescription extends StatelessWidget {
const _VideoDescription({
Key key,
this.title,
this.user,
this.viewCount,
}) : super(key: key);
final String title;
final String user;
final int viewCount;
...
}
While in the second snippet, I am getting an error when I place the variable initiation after the constructor and give it a type of final. Hence this structure.
class Category {
String imgUrl;
String name;
Category(name, imgUrl) {
this.imgUrl = imgUrl;
this.name = name;
}
}
Another thing, what is the use of : super(key: key); at the end of the constructor on the first snippet?
From the docs:
By default, a constructor in a subclass calls the superclass’s unnamed, no-argument constructor. The superclass’s constructor is called at the beginning of the constructor body. If an initializer list is also being used, it executes before the superclass is called. In summary, the order of execution is as follows:
initializer list
superclass’s no-arg constructor
main class’s no-arg constructor
Regarding final variables you can do the following two ways:
class Category {
final String imgUrl;
final String name;
Category(this.imgUrl,this.name);
}
or:
class Category {
final String imgUrl;
final String name;
Category(imgUrl,name)
: imgUrl = imgUrl,
name = name;
}
Basically the final variables need to be initialized before the constructor body is executed, since the final variable cannot change.
Regarding the super check the following:
void main() {
var students = Students(1, "peter");
print(students.name);
}
class Students extends Person {
final int id;
Students(id, age)
: id = id,
super(age) {
print("I'm the constructor body");
}
}
class Person {
final String name;
Person(name) : name = name {
print("I'm the super constructor");
}
}
This will print:
I'm the super constructor
I'm the constructor body
peter
So here since you have final variables then you need to create an initializer list to initialize these variables and since Students extends Person and since the super class Person doesnt have a no-argument constructor, then you must call super(age). The order of execution will be the same as explained above.
class LevelUp extends GetxController {
Map<String, String> params = Get.arguments;
var myTest = params.[comLevel];
}
Error report--"The instance member 'params' can't be accessed in an initializer." I am new to programming and this is being called directly from a widget. I checked the LevelUp map and it has contents. The error occurs where I am trying to assign the param value to myTest. It doesn't matter if I put the key in quotes or provide an integer. Any advice would be greatly appreciated.
You can't access params before you've initialized the object. To fix your example, move your myTest initialization into a constructor.
Also, I don't believe you should have a period before [comLevel].
class LevelUp extends GetxController {
Map<String, String> params = Get.arguments;
String myTest;
LevelUp() {
myTest = params[comLevel];
}
}
Null safety update:
Use late keyword: Dart 2.12 comes with late keyword which helps you do the lazy initialization which means until the field bar is used it would remain uninitialized.
class Test {
int foo = 0;
late int bar = foo; // No error
}
Although this question has been answered for the OP's case, I want to offer a solution to those receiving this error in a StatefulWidget scenario.
Consider a situation where you would want to have a list of selectable items that dictate which category to display. In this case, the constructor might look something like this:
CategoryScrollView({
this.categories,
this.defaultSelection = 0,
});
final List<String> categories;
final int defaultSelection;
Note the property defaultSelection is responsible for specifying which category should be selected by default. You would probably also want to keep track of which category is selected after initialization, so I will create selectedCategory. I want to assign selectedCategory to defaultSelection so that the default selection takes effect. In _CategoryScrollViewState, you cannot do the following:
class _CategoryScrollViewState extends State<CategoryScrollView> {
int selectedCategory = widget.defaultSelection; // ERROR
#override
Widget build(BuildContext context) {
...
}
}
The line, int selectedCategory = widget.defaultSelection; will not work because defaultSelection it hasn't been initialized yet (mentioned in other answer). Therefore, the error is raised:
The instance member 'widget' can't be accessed in an initializer.
The solution is to assign selectedCategory to defaultSelection inside of the initState method, initializing it outside of the method:
class _CategoryScrollView extends State<CategoryScrollView> {
int selectedCategory;
void initState() {
selectedCategory = widget.defaultSelection;
super.initState();
}
A simple example, where it shows how we can resolve the above issue,
Example: Create an instance of class B, and pass an instance of class A in the parameter of it
WRONG(Compile time error of initializer):
final A _a = A();
final B _b = B(_a);
shows error: The instance member '_a' can't be accessed in an initializer.
Right:
final A _a = A();
late final B _b;
AppointmentRepository() {
_b = B(_a);
}
#100% working solution
:
Juts place var myTest = params.[comLevel];
below your Build method.
eg.
class LevelUp extends GetxController {
Map<String, String> params = Get.arguments;
Widget build(BuildContext context) {
var myTest = params.[comLevel];
}
}
For me it happened Because i was trying to access a Property of a class instance (Lets Say Class A ) And Use this property to initialize Another Class (Class B) , The Property Was Integer Number and Was Defined
However , Since i didn't Make an Object from "Class A" I can access those propertied Belong to it !
I tried to use this property inside the "Build" Method so that an object is "Created/Built" And it Worked !
I also got the similar error.
And I found the solution as follows.
My first code:
final BuildContext mycontext = GlobalContextClass.navigatorKey.currentContext;
final PsValueHolder psValueHolder = Provider.of<PsValueHolder>(mycontext, listen: false);
Next is the code where the error is fixed:
final PsValueHolder psValueHolder = Provider.of<PsValueHolder>(GlobalContextClass.navigatorKey.currentContext, listen: false);
Instead of defining 2 variables in a row, I placed the first variable directly in the place of the 2nd variable.
Another solution is making your variable, a GetX parameter.
int count_myProducts = cartItems.length; //The instance member 'cartItems' can't be accessed in an initializer. (Documentation)
int get count_myProducts => cartItems.length;
see this video at 27:34
GetX State Management tutorial with Flutter
https://www.youtube.com/watch?v=ZnevdXDH25Q&ab_channel=CodeX
Just carry
var myTest = params.[comLevel];
into Widget build{} below.
like this :
class LevelUp extends GetxController {
Map<String, String> params = Get.arguments;
Widget build(BuildContext context) {
var myTest = params.[comLevel];
}
}
I am passing variables from one activity to another in flutter but getting the error "Instance member ‘latitude’ can’t be accessed using static access" I need it converted in that block so I can assign it to a static URL.
class Xsecond extends StatefulWidget {
final double latitude;
final double longitude;
Xsecond(this.latitude, this.longitude, {Key key}): super(key: key);
#override
_Xsecond createState() => _Xsecond();
}
class _Xsecond extends State<Xsecond> {
static String lat = Xsecond.latitude.toString(); // Error: Instance member ‘latitude’ can’t be accessed using static access
...
followed by
...
String url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${lat},$lng&radius=$radius&type=restaurant&key=$api';
...
In your code both latitude and longitude are defined as non-static i.e. are instance variables. Which means they can only be called using a class instance.
class _Xsecond extends State<Xsecond> {
final xsecond = Xsecond();
static String lat = xsecond.latitude.toString();
...
Please read the basics of any Object Oriented Programming language e.g. Dart, java, C++
However, in your context the first class is your StatefullWidget. So you can access that by the widget field of your state class.
FIX:
class _Xsecond extends State<Xsecond> {
static String lat = widget.latitude.toString();
...
This error occurs if you use non-static variable like static. Let's take a look at this example:
class MyPage extends StatefulWidget {
final foo = Foo();
// ...
}
class _MyPageState extends State<MyPage> {
final newFoo = MyPage.foo; // Error
// ...
}
MyPage.foo isn't a static member but you are using if it was.
To solve this issue, you can either make the variable static
static final foo = Foo();
or
Use widget variable to get hold of the underlying variable.
class _MyPageState extends State<MyPage> {
#override
void initState() {
super.initState();
final newFoo = widget.foo; // No Error
}
// ...
}
I have a stateless widget and while writing the code I am using a non-final field in the stateless widget and the ide keeps giving me warning that all the fields in stateless widget should be final
But I don't understand why having a non-final field in stateless widget be a problem.
I think it should be perfectly fine to have non-final field because there could be a field that we don't want to modify later but this field can only be initialized inside the constructor function so, for that you need to use non-final field
example:
class Temp extends StatelessWidget {
final int a;
final int b;
int c;
temp({this.a, this.b}) {
this.c = this.a + this.b;
}
#override
Widget build(BuildContext context) {}
}
In the above widget, I can't make c as final because it is initialized inside the constructor function even though I have no plans to change the c variable in the future.
If having a non-final field in a Stateless widget is not a good Idea then How to handle the above situation.
Note: I cannot use the Constructor() : [initialization] {} because the initialization can involve the function or loops
StatelessWidget class A widget that does not require mutable state, so the class is marked as #immutable, Dart language do the best to fix your errors, so "final" keyword will just warn you about that but will not stop the compiling, you can use your code normally without final keyword if you are sure it will initialized one time and not change again at run-time ..
and this is the main reason to have 2 keywords (final, const) for define constants in Dart language
Both final and const prevent a variable from being reassigned.
const value must be known at compile-time, const birth = "2020/02/09". Can't be changed after initialized
final value must be known at run-time, final birth = getBirthFromDB(). Can't be changed after initialized
You can use initialization even for function invocation.
here is an example:-
class SumWidget extends StatelessWidget {
final int sum;
static getSum(List<int> items) {
int perm = 0;
for (var value in items) {
perm += value;
}
return perm;
}
SumWidget(List<int> roles) : this.sum = getSum(roles);
#override
Widget build(BuildContext context) {}
}
but function must be static because The instance member can't be accessed in an initializer.