Dart Flutter How to initialize a class method inside of its class? - flutter

Here is my class:
class WorldTimeClass {
String flag;
String url;
String time;
String location;
WorldTimeClass({this.flag, this.url, this.time, this.location});
Future<String> getData() async {
try{
Response load = await get('http://worldtimeapi.org/api/timezone/$url');
Map x(){if(load.statusCode == 200){
print(load.statusCode);
Map map = jsonDecode(load.body);
return map;}
else{
print('No Access');
return {1:'NoAccess.'};}
}
Map myMap = x();
String datetime = myMap['utc_datetime'];
String offsetUTC = myMap['utc_offset'];
DateTime dateTimeObjectConvert = DateTime.parse(datetime);
// Below converts the datetime string to a DateTime Object and then converts the UTC Offset to a substring only '01' out of +01:00 and then converts it to an int Object and then adds it to the DateTime Object as a Duration (hours);
dateTimeObjectConvert = dateTimeObjectConvert.add(Duration(hours: int.parse(offsetUTC.substring(1,3))));
return time = dateTimeObjectConvert.toString();
}
catch(e,s){
return 'Could not access time data from API.\nWe are sorry, please try again.\nError occured: $e';
}
}
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
}
How can I access myString and execute it inside my class in order to use the resulting String object to use it inside a second method pretty ?
Also, I need to understand what does the below exception mean?
Only static members can be accessed in initializers.

Only static members can be accessed in initializers.
This basically means that you cannot call methods of a class or access properties of a specific class directly under class declaration.
You are getting the error on those two lines:
var myString = getData().then((value) => value);
DateFormat pretty = DateFormat().add_jm().format(myString);
Therefore create a method that returns a String then all you have to do is to call that method and it will give you the String, and add the code above inside the method:
String getDateFormat(){
var myString = getData().then((value) => value);
return DateFormat().add_jm().format(myString);
}

To access your myString variable you'll have to do one of those things:
Instantiate an WorldTimeClass object and access it using yourWorldClassObject.myString
Make it into in static member by using the static keyword like static var myString. This is what " Only static members can be accessed in initializers. " is all about. You have to create an instance of the class if you want to access it's properties, or make them static to access them without the need to instantiate an object. Simply WorldTimeClass.myString.

Related

Flutter dart replace replace Json object with variables

In this case I have class. Where I took a variable. Also I have a Json map. So I want to change Json map object replace with variables. Here is my code example....
So how can I achieve that
I want replace Json object with dart variable
class Data {
late String slug;
Map<String, String> singleProductVariable = {"slug": "$slug"};
}
Firstly, there is no JSON in your code sample.
I assume that you would like to set the value of the corresponding key in your Map when setting the variable.
If so, you might want to use a setter in a next way:
class Data {
String _slug;
late Map<String, String> v = {"slug": _slug};
Data(String slug) : _slug = slug;
set slug(String str) => v['slug'] = str;
}
void main() {
final d = Data("slug");
print(d.v);
d.slug = "newSlug";
print(d.v);
}
The output of the code above will be:
{slug: val}
{slug: newVal}

Creating and using Singleton in flutter dart

I am very new to flutter and dart and trying to use singleton instance for global state(?).
which is company info that gets from backend server.
When flutter app starts, send request to the server and get a response and build a singleton instance based on the response.
So I created class
class Company {
static final Company _instance = new Company._internal();
factory Company() {
return _instance;
}
#protected
String name;
#protected
String intro;
String get companyName => name;
String get companyIntro => intro;
void setCompany(String name, String intro) {
name = name;
intro = intro;
}
Company._internal();
}
in main.dart
// companyResult is the response from server
final String companyName = companyResult["name"];
final String companyIntro = companyResult["intro"];
// create singleton instance
var company = Company();
// set company info
company.setCompany(companyName, companyIntro);
// cheking
print(company.companyName)
prints null
What am I doing wrong?
Singletons are better avoided, I would recommend that you use Provider instead and inject a simple object reference on your widget tree, so you can grab that reference whenever you want.
The reason your example prints null is because you are wrongly referencing your variables on setCompany(), the variables name and intro are all the same variable, you are changing the variables internal to the function, not the class variables, in order to fix it change it to:
void setCompany(String name, String intro) {
this.name = name;
this.intro = intro;
}
Also, I would suggest you name your variables _name and _intro, as there's no sense in having a get for a variable that's no private.

How to concatenate a class with a variable to get a static variable from this class?

I am making a pokemon app and I have a question that I already had in other projects and I would like to know if anyone can help me with a solution.
I receive a variable called pokemonName from other screen, I want to pass the variable and concatenate with the class "Strings", it will be like Strings.+pokemonName.toLowerCase(), converting to lowercase to get the map from the class Strings, but I don't know how to achieve this to remove the switch and don't need to use a lot of cases for each pokemon.
class PokemonDetailScreen extends StatelessWidget {
final String pokemonName;
final String image;
Map<String, dynamic> pokemonMap = {};
PokemonDetailScreen(this.pokemonName, this.image, this.index){
getPokemonMap();
}
#override
Widget build(BuildContext context) {
return Container();
}
void getPokemonMap(){
switch(pokemonName){
case "Bulbasaur":
pokemonMap = Strings.bulbasaur;
break;
case "Charmander":
pokemonMap = Strings.charmander;
break;
}
}
}
**Class in another dart file:**
class Strings {
static Map bulbasaur = {};
}
What I needed is something like this:
void getPokemonMap(){
pokemonMap = Strings.$pokemonMap.toLowerCase();
}
What you could do is have a static map indexed by the name of your Pokemons and whose values are maps.
class Strings {
static Map<String, dynamic> map = {
'Bulbasor': {},
'Charmander': {},
// ...
};
}
And you’ll use it like this: pokemonMap = Strings.map[pokemonName].
~You can use JSON file to do all this things instead use a class.~
I recommend not use a static class to do that thing, instead you can just make a normal class and instantiate on another file, so when the class that you call your another class will be dispose when the parent was.
class PokemonStrings {
Map bulbasaur = {your map here};
}
To call that in another file you need just do
PokemonString _pokemonString = PokemonString();
And call whatever you need in the class that you instantiate
var bulbasaurMap = _pokemonString.bulbasaur;
But even so you need walk with static class. Just call the name of class followed by dot to access all the static attributes
var bulbasaurMap = PokemonString.bulbasaur;

Passing constructor as argument in Flutter

I have API communication service in my Flutter app with 10+ different services, and 100+ API calls that heed to parse data. In order to reuse code I've decided to create some common parsing code that is going to parse data from API:
ApiResponse handleObjectResponse({
#required http.Response serverResponse,
#required Function objectConstructor,
}) {
if (serverResponse.statusCode == 200) {
dynamic responseObject = objectConstructor(json.decode(serverResponse.body));
return ApiResponse(responseObject: responseObject);
} else {
ApiError error = responseHasError(serverResponse.body);
return ApiResponse(error: error);
}
}
This way I am able to parse JSON object from API in a reusable way no matter what the Object class is, just by passing constructor function to this method.
When I call this method in any of the Services I've created for fetching data like this:
handleObjectResponse(serverResponse: response, objectConstructor: ChartData.fromJson);
I get error: The getter 'fromJson' isn't defined for the class 'ChartData'.
Try importing the library that defines 'fromJson', correcting the name to the name of an existing getter, or defining a getter or field named 'fromJson'.
Where I think the problem is is in this model class and factory statement, but I don't know how to fix it:
class ChartData {
List<ChartDataPoint> points;
ChartData({
this.points,
});
factory ChartData.fromJson(Map<String, dynamic> json) {
List jsonPoints = json["data"];
return ChartData(
points: List.generate(jsonPoints.length,
(i) => ChartDataPoint.fromJsonArray(jsonPoints[i])));
}
}
You cannot pass constructors as functions. You need to create a function what will call the constructor instead:
(int a) => Foo(a);
Just a 2022 update: since 2.15 it's possible by Class.new, see the complete issue: https://github.com/dart-lang/language/issues/216.
class A {
final String a;
const A(this.a);
#override
String toString() => 'A($a)';
}
class B {
final String b;
const B(this.b);
#override
String toString() => 'B($b)';
}
void main() {
final List<Object Function(String)> constructors = [A.new, B.new];
for (final Object Function(String) constructor in constructors) {
final Object instance = constructor('My Constructor Parameter');
if (instance is A) {
print(instance.toString());
}
}
}
Note that if you're using named params, both class constructors must have the same param name, otherwise the constructor signatures won't match and then it will generate this static error:
The element type X can't be assigned to the list type Y.

How to return an object or struct from a method in MQL?

struct Person {
string FirstName;
string LastName;
};
class Builder {
public:
Person Builder::Build() {
Person person;
person.FirstName = "FirstName";
person.LastName = "LastName";
return person;
};
};
When I compile this it gives me the below error:
'return' - structure have objects and cannot be copied.
I just need to create a struct or class object and return it, I don't want to do any copying.
I tried using & and * combinations but didn't work. I tried with a class instead of struct and it didn't work either.
I also tried with class as shown below:
class Person {
public:
string FirstName;
string LastName;
};
class Builder {
public:
Person* Build() {
Person person;
person.FirstName = "FirstName";
person.LastName = "LastName";
return &person;
};
};
int OnInit()
{
Builder builder;
Person* person = builder.Build();
string firstName = person.FirstName;
return(INIT_SUCCEEDED);
}
And it gives me invalid pointer access when accessing person.FirstName in the OnInit() method at runtime.
Found the answer but how to avoid memory leak? how to destruct the object and its pointer after use?
class cPerson {
public:
string FirstName;
string LastName;
};
class cBuilder {
public:
cPerson* Build() {
cPerson* person = new cPerson();
person.FirstName = "firstname";
return person;
};
};
cBuilder builder;
cPerson* person = builder.Build();
string age = person.FirstName;
You can delete the object by delete(person); and if you are unsure the object is not a null, it is better to check if(CheckPointer(object)==POINTER_DYNAMIC)delete(object);
Overall you should have all such objects as variables with corresponding variable names, or keep them all in a collection and destroy the whole collection at end. You may also create global variable of object (before OnInit, not inside any function) and it is to be deleted at end of program.
Regarding the initial question - you cannot have string inside a struct, only primitives
you should NOT delete static objects - you will get "delete invalid pointer"-message from compiler in print area... therefore the check should be done as Daniel Kniaz answered... but as so as you are creating the object inside the wrapper - you'd better have a check for deletion & delete it in the Destructor of its wrapper (though I doubt, that you really should use here another class for CPerson creation - yuo can create its object in its - CPerson's - Constructor)
First you need a default constructor and copy constructor in your code. second you need to initialize the struct to default value, the struct only allocate space in the memory and not initialize it, so you can end up with cases where a long variable has some weird value like -1823834393939, so always set your struct to default values.
then when you return a class or struct from a function. the copy constructor will be called that copy the values. so if you don't want to return the exact object you've created in your class you don't need to return a reference
struct Person
{
string FirstName;
string LastName;
Person()
{
FirstName = "";
LastName = "";
}
Person(Person &that)
{
FirstName = that.FirstName;
LastName = that.LastName;
}
};
class Builder
{
public:
Person Builder::Build(string argFirstname, string argLastName)
{
Person person;
person.FirstName = argFirstname;
person.LastName = argLastName;
return person;
};
};
void OnStart()
{
Builder b;
Person p = b.Build("Mohammad Hossein", "amri");
Print(p.FirstName + " " + p.LastName);
}
the output will be