I am learning Flutter(Mostly from Youtube) & while learning it I have seen many instructor have used a statement like this,
final SomeClass someVariable = const SomeClass(withSomeValue);
What bothers me that why do we need to use const keyword after the assignment operator there since we already made it a final & I already know that final keyword is used to define a constant variable. So what does const signifies here?
It's a memory optimization possible with immutable objects.
const instances are shared:
final a = const Whatever();
final b = const Whatever();
print(identical(a, b)); // true
In this snippet, both a and b share the same object instance, so it is allocated only once.
Here, the object allocation, takes place just once, so it is good for performance.
final Test test = const Test();
final Test test2 = const Test();
Here it takes place twice.
final Test test = Test();
final Test test2 = Test();
Related
I'm trying to use a version of nested classes to make a tree of constant strings throughout my app in Flutter. I'd like them to be nested in order to find const strings quickly as the app grows, but still have the additional 'speed' of using the const keyword for Text() widgets.
However, I'm having a hard time trying to use them in const Text() widgets.
Here's a sample:
class Strings {
static const String ok = 'OK';
static TechnicianStrings technicianStrings = TechnicianStrings();
}
class TechnicianStrings {
TechnicianStrings();
final String createTech = 'Create Technician';
final String technician = 'Technician';
}
Throughout the app, I'd like to use these constant Strings as so:
const Text(Strings.ok), // <-- this works
const Text(Strings.technicianStrings.technician), //<-- only works without 'const'
const Text(Strings.technicianStrings.createTech), //<-- only works without 'const'
However, I get an error of "Arguments of a constant creation must be constant expressions" when I use the const keyword for the text widgets.
I've tried to use varying "const and static" names for the members of TechnicianStrings, and I get errors such as "invalid Constant" for the text widget. I also defined TechnicianStrings as static const, and got an error of 'Constant variables must be initialized with a constant value' for the line:
static const TechnicianStrings technicianStrings = TechnicianStrings();
Is there a way to use such a nested class structure hand in hand with const Text() widgets?
You need a constant constructor in TechnicianStrings.
class Strings {
static const String ok = 'OK';
static const TechnicianStrings technicianStrings = TechnicianStrings();
}
class TechnicianStrings {
const TechnicianStrings(); // <---
final String createTech = 'Create Technician';
final String technician = 'Technician';
}
Check these two examples:
static const inside of class:
class SessionStorage {
static const String _keySessionExist = 'storage.key';
}
Just a const outside of the class:
const String _keySessionExist = 'storage.key';
class SessionStorage {
}
Is there any difference or implications between having a static const variable inside of a class or just having it declared as const outside of it in Dart?
Maybe the compiled code changes?
Which one is more performant?
Which one should we follow if the variable is private to the file?
The declaration for cons must be using const. You have to declare it as static const rather than just const.
static, final, and const mean entirely distinct things in Dart:
static means a member is available on the class itself instead of on instances of the class. That's all it means, and it isn't used for anything else. static modifies members.
final means single-assignment: a final variable or field must have an initializer. Once assigned a value, a final variable's value cannot be changed. final modifies variables.
const has a meaning that's a bit more complex and subtle in Dart. const modifies values. You can use it when creating collections, like const [1, 2, 3], and when constructing objects (instead of new) like const Point(2, 3). Here, const means that the object's entire deep state can be determined entirely at compile time and that the object will be frozen and completely immutable.
Const objects have a couple of interesting properties and restrictions:
They must be created from data that can be calculated at compile time. A const object does not have access to anything you would need to calculate at runtime. 1 + 2 is a valid const expression, but new DateTime.now() is not.
They are deeply, transitively immutable. If you have a final field containing a collection, that collection can still be mutable. If you have a const collection, everything in it must also be const, recursively.
They are canonicalized. This is sort of like string interning: for any given const value, a single const object will be created and re-used no matter how many times the const expression(s) are evaluated. In other words:
getConst() => const [1, 2];
main() {
var a = getConst();
var b = getConst();
print(a === b); // true
}
I think Dart does a pretty good job of keeping the semantics and the keywords nicely clear and distinct. (There was a time where const was used both for const and final. It was confusing.) The only downside is that when you want to indicate a member that is single-assignment and on the class itself, you have to use both keywords: static final.
Also:
I suggest you to have a look at this question
What is the difference between the "const" and "final" keywords in Dart?
Is there any difference or implications between having a static const variable inside of a class or just having it declared as const outside of it in Dart?
The obvious difference is that the static version must be referenced with the class name. Other than the change in name resolution, the should be the same.
Maybe the compiled code changes?
Which one is more performant?
They're both compile-time constants. There shouldn't be any difference.
Which one should we follow if the variable is private to the file?
If you want something that's private to a Dart library (which usually means the file), then prefix it with _. It doesn't matter whether it's global or static.
In consts class, I have declared this
Consts
static const URL = "";
In login bloc, after login successfully,server will return the url to me, and I assign the url to this variable.
Response user =
await _repo.getLogin(context, email, password);
var baseResponse = UserResponse.fromJson(user.body);
if (baseResponse.status == 101) {
Consts.URL = baseResponse.url;
}
In repo class, assume I have 5 methods, I need to use the url in consts class.Is it a good solution and possible?
Future create(){
try{
var request = http.MultipartRequest('POST',Uri.parse(Consts.URL));
}catch(e){
}
}
You cannot assign a value to a const during run time since const is a compile-time constant.
Please refer documentation on https://dart.dev/guides/language/language-tour#final-and-const
Final and const If you never intend to change a variable, use final or
const, either instead of var or in addition to a type. A final
variable can be set only once; a const variable is a compile-time
constant. (Const variables are implicitly final.) A final top-level or
class variable is initialized the first time it’s used.
I have a variable list in flutter that won't change anymore once called. The question is: can I make this list constant?
Here is the code:
final number = new List<int>.generate(300, (i) => i + 1);
var rng = new Random();
final place = new List.generate(300, (_) => rng.nextInt(3));
final noteListStart = new List<Note>.generate(number.length, (i) => Note(number[i],place[i]));
final List<Note> noteListEnd = [
Note(300, -1), Note(301, -1),Note(302, -1),Note(303, -1)
];
final initList = List<Note>.from(noteListStart)..addAll(noteListEnd);
List<Note> initNotes1() {
return
initList;
}
In the example above, initNotes1() needs to be constant after being called so I can use it easely somewhere else in the code.
Any help would be appreciated.
At this point, it is unclear what your actual question is.
Taken at face value, you are asking how you can compute a list at runtime and then, once the list is populated, convert it into a constant. Well the answer is this: you can't.
Constants are explicit values that are defined before the program has even compiled. By definition, you cannot create a constant from a computed or generated value (unless it is evaluated from simple expressions involving other values are themselves constant). This means you can't create a constant list full of random values - it is antithetical to the whole concent of what a "constant" is.
(Note: This explanation is a bit specific to Dart, but it is also common among compiled languages. This is different to the definition of a "constant" for an interpreted language such as Javascript, which uses the const keyword to merely refer to an immutable variable.)
If you didn't mean "constant" and merely meant "immutable", then you would mark your list as final which would achieve the same thing. As an extra added measure, you can create the list using List.unmodifiable to make it so its elements couldn't be changed either.
final rng = Random();
final _noteListStart = List.generate(startLength, (i) => Note(i + 1, rng.nextInt(3)));
final _noteListEnd = [
Note(300, -1), Note(301, -1),Note(302, -1),Note(303, -1)
];
List<Note> noteList = List.unmodifiable([..._noteListStart, ..._noteListEnd]);
However, what it appears you are asking is not how to make a variable constant, but instead how to make a variable global. This is a question that is both easier and harder to answer.
It's easier because doing so is quite simple. Take the above code, rearrange it a bit, and put it into its own dart file which you can then import and use wherever you wanted:
// notes_list.dart
final _noteListEnd = [
Note(300, -1), Note(301, -1),Note(302, -1),Note(303, -1)
];
List<Note> _initList(int startLength) {
final rng = Random();
final _noteListStart = List.generate(startLength, (i) => Note(i + 1, rng.nextInt(3)));
return List.unmodifiable([..._noteListStart, ..._noteListEnd]);
}
final List<Note> noteList = _initList(300);
// other_file.dart
import '/path/to/notes_list.dart';
void main() {
print(noteList);
}
(Note: The import is mandatory - you cannot make anything _truly_ global in Dart and eliminate the need to import it.)
On the flip side, this question is harder to answer because the practice of making global variables is frowned upon by many programmers. It belongs to a class of practices that leads to tightly coupled and difficult-to-test code which in turn results in programs that are near impossible to maintain and evolve. In many cases, global variables can be replaced entirely by another practice, such as dependency injection.
There is an analyzer/lint check to warn me when it is possible to use a const constructor: https://dart-lang.github.io/linter/lints/prefer_const_constructors.html
(ie. using final a = const A(); instead of final a = A();)
I think to understand the advantages (there will only ever be one instance with the same constant values for a const constructor). But why isn't this the default? Since dart 2 the new can be omitted, so why didn't they change the definition of creating a new instance which can be created const simply as const instead of new? I assume there must be some disadvantage to having everything const?
(for example in a constant context like const [A()] it is actually the same as const [const A()], so why not everywhere)?
so why didn't they change the definition of creating a new instance which can be created const simply as const instead of new?
If you mean why doesn't final a = A(); automatically assume const A() if A has a const constructor:
Sometimes it is automatic:
const a = A();
in which case A's constructor is being invoked in a const context and doesn't need an extra const qualifier on the right-hand-side.
An explicit const expresses intent. For example, suppose you had:
final a = A(B());
where A and B have const constructors. Later, somebody makes a change:
final a = A(C());
where C does not have a const constructor. If const were automatic, then you would have no idea that a is no longer const. Maybe that's okay, but it also could suddenly have a negative impact on your application's performance, and without an explicit const qualifier, the impact of a local change could have a much wider scope than expected. (That said, explicit const qualifiers and automatically adding them aren't mutually exclusive.)
const can have downsides. const creates compile-time constants. If you have:
final a1 = A();
final a2 = A();
identical(a1, a2) is not true. If const A() were implicit, then identical(a1, a2) would be true, and maybe that's not a property that the code intended to have.
Compile-time constants live forever. The whole point is to have an object that can be reused instead of re-constructing it. The flipside is that won't be destroyed.