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.
Related
I have a file called database.dart. In it, I have a string property called currentUsername. This is the currently logged in user's username. I want this class to call the getUsernameFS() function only once and then be able to reuse this string for the rest of the class's existence inside its other functions. How do I accomplish this?
The code below gives an error: Error: A value of type 'Future<String>' can't be assigned to a variable of type 'String'.
class Database {
late String currentUsername = getUsernameFS(); //ERROR IS HERE
Future<String> getUsernameFS() async {...}
String someFunction() {...//some function that uses currentUsername//...}
}
A direct (and perhaps naive) approach would be to add an asynchronous initialization step to initialize an instance of your class:
class Database {
late String currentUsername;
Future<void> initialize() async {
currentUsername = await getUsernameFS();
}
}
However, that's potentially error-prone since it creates more work for callers, and callers could accidentally neglect to call (or neglect to wait for) initialize, and there's no way to enforce that at compile-time.
Instead, I'd recommend a couple of other options:
Make your member variable a Future instead:
late Future<String> currentUsername = getUsernameFS();
This has the advantage of safely avoiding accidental errors from callers who neglect to explicitly call an asynchronous initialization method first. However, this has the disadvantage of forcing all callers to await the result, making them also asynchronous.
If possible, make your class constructor private and force callers to obtain instances with an asynchronous, factory-like static method:
class Database {
late String currentUsername;
Database._();
static Future<Database> create() async {
var db = Database._();
db.currentUsername = await db.getUsernameFS();
return db;
}
...
}
This also has the advantage of safely avoiding accidental errors, and it avoids forcing all consumers of currentUsername to be asynchronous. A disadvantage is that a private constructor would prevent your class from being extended.
If possible, I'd also make getUsernameFS a static method and pass the username to the private constructor. Then currentUsername wouldn't need to be late, and you would avoid any risk of accidentally using a late variable before it's initialized.
I am trying to access a variable called _countryfrom another file in dart, but an error occured: The getter '_country' isn't defined for the type 'CurrentCountry'.
Here's the code where the variable I want to access is(in another file):
class CurrentCountry {
static String _country = 'All';
}
And here's the code where I want to access the variable:
Future<Map<String, dynamic>> fetchWorldData() async {
Response activeResponse = await get(Uri.parse(
'https://disease.sh/v3/covid-19/countries/${CurrentCountry._country}'));
return json.decode(activeResponse.body);
}
If you can help me, I will be very grateful.
You should remove the underscore of the variable.
If an identifier starts with an underscore (_), it’s private to its
library
Reference here: Dart language Important concepts
I have a class that I am creating that looks like this:
class Movie {
final String title, posterPath, overview;
Movie(this.title, this.posterPath, this.overview);
Movie.fromJson(Map json) {
title = json["title"];
posterPath = json["poster_path"];
overview = json['overview';
}
}
I am getting a warning that says that "The final variables 'overview', 'posterPath', & '1' more must be initialized. There are also warnings around each variable saying 'title' can't be used as a setter because it is final.
When I write the constructor using this syntax, the warnings go away:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
What exactly is going on here?
Dart objects must be fully initialized before anyone gets a reference to the new object. Since the body of a constructor can access this, the object needs to be initialized before entering the constructor body.
To do that, generative Dart constructors have an initializer list, looking similiar to C++, where you can initialize fields, including final fields, but you cannot access the object itself yet. The syntax:
Movie.fromJson(Map json)
: title = json["title"],
posterPath = json["poster_path"],
overview = json['overview'];
uses an initializer list (the list of assignments after the :) to initialize the final instance variables title, posterPath and overview.
The first constructor uses an "initializing formal" this.title to directly put the parameter into the field.
The constructor
Movie(this.title, this.posterPath, this.overview);
is effectively a shorthand for:
Movie(String title, String posterPath, String overview)
: this.title = title, this.posterPath = posterPath, this.overview = overview;
Your constructor can combine all of these and a body:
Movie(this.title, this.posterPath, String overview)
: this.overview = overview ?? "Default Overview!" {
if (title == null) throw ArgumentError.notNull("title");
}
(A const constructor cannot have a body, but it can have an initializer list with some restrictions on the allowed expressions to ensure that they can be evaluated at compile-time).
Dart separates properties initialization from the constructor body.
A constructor has 3 parts :
the name/parameters definition
properties initialization/super call/asserts
A body, similar to a function immediately run on construction
Both the initialization and body parts are optional.
final variables must be initialized on the first 2 parts. They cannot be initialized inside the body.
A full constructor will look like the following :
MyClass(int value)
: assert(value > 0),
property = value,
super();
{
print("Hello World");
}
The main purpose of this initializer part is for body-less constructors which allows const constructors, a dart specific feature. See How does the const constructor actually work? for more details on these.
I just found some documentation around this, & it seams that the second version with the : is what's called the "initializer list" which allows you to initialize instance variables before the constructor body runs.
There is more detail around this in the documentation here.
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();
I don't really understand how required works. For example I've seen this code:
class Test{
final String x;
Test({
required this.x
});
factory Test.initial(){
return Test(x: "");
}
}
But what should required do here? Seems like it makes an optional parameter a non optional parameter.
Update
As of Dart 2.12, the required keyword replaces the #required meta annotation. For detailed info look into the official FAQ. The following answer has been updated to reflect both this and null safety.
Parameters required by default
The parameters of a class constructor or function are required by default.
class Test {
final String x;
Test(this.x);
}
You're not allowed to do this:
final value = Test();
// 1 positional argument(s) expected, but 0 found.
You must do this:
final value = Test('hello');
Optional named parameters
If you surround a parameter with curly braces, though, in addition to becoming a named parameter, it also becomes optional.
Since it's optional, the property must either be nullable like this:
class Test {
final String? x;
Test({this.x});
}
Or it has to have a default value like this:
class Test {
final String? x;
Test({this.x = ''});
}
So now this is ok:
final value = Test();
And so is this:
final value = Test(x: 'hello');
Required named parameters
Sometimes you don't want to allow a parameter to be null and there is no natural default variable. In that case you can add the required keyword in front of the parameter name:
class Test {
final String x;
Test({required this.x});
}
This is not ok anymore:
final value = Test();
// The named parameter 'x' is required, but there's no corresponding argument.
But this is still fine:
final value = Test(x: 'hello');
Dart 2.12 (null safety):
Beginning with Dart 2.12, the #required annotation is now replaced by the required keyword. You should mark your field required if it is mandatory for others to pass some value to it.
For example:
class Foo {
final int a; // Mandatory? Use 'required'
final int b; // Not mandatory? Don't use 'required'
Foo({
required this.a, // Marked 'required'
this.b = 1,
});
}
Usage:
Foo(); // Error: 'a' is required
Foo(a: 0); // Good
Foo(a: 0, b: 1); // Good
#required is an annotation that will create a warning for you to remember that the named parameter is necessary for the class to work as expected.
It will not create compile errors, at least for what I know.
#required bounds you to pass #required marked arguments while creating object of Class. For example, while showing a dialog, you'd mark context as required since, you cannot show dialog without having a valid context. But, you should not overuse it.
Short answer: Named parameters are optional by default in Dart. We prefer them to positional params for ease of use. In this case, the named parameters also might be expected to hold some value all the time (non-nullable) - from initialization itself. Hence, the double effort.
He could use default value initialization of the parameters instead of 'required', if the values were compile-time constants, and that doesn't seem to be the case here.
Positional parameters can be required or optional, which we pass in order when calling. The following is an example of required positional parameters' usage:
class Object{
String name;
int value;
Object(this.name, this.value=100); //auto type inference
}
final one = Object("Name here", 50); // All parameters are needed to call.
Named parameters are another type of optional parameters. Flutter APIs use named parameters and in our UI code, it is preferred to use named parameters instead of positional parameters. Reason being readability and clarity when reading code or calling the constructors later on at several parts of the code. You would have seen this as the case with all Widgets, Styles. For if it were to be positional it would be difficult to keep track of them upon calling with the sheer amount of methods that would be in use, and dynamic type inference could also be at work.
void display({required String name, int value1, int value2=100}) {...;} //named params
display(value1: 50, name: "Calculated name");
NOTE:
If exists, required positional parameters have to come first. Either named or optional positional params can follow(NOT BOTH).
String say(String from, String msg, [String? device]) { //req. pos params and opt pos params.
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
Remove
required
in constructor.
Instead write
final String? x;
So, it becomes as:
class Test{
final String? x;
Test({
this.x
});
factory Test.initial(){
return Test(x: "");
}
}