I'm trying to use the #factoryParam annotation of injectable package by using it in a class. But whenever I try to run the build runner to generate the config file, it gives me an error saying the Factory params must be nullable.
import 'package:injectable/injectable.dart';
#injectable
class QuoteRepository {
const QuoteRepository(
#factoryParam String env)
: _env = env;
final String _env;
String getQuotes() {
return _env;
}
}
Error:
[SEVERE] injectable_generator:injectable_builder on features/testing_view_model.dart:
Factory params must be nullable
package:features/testing_view_model.dart:6:28
╷
6 │ #factoryParam String env)
│ ^^^
Try changing it to String? This will enable a String to be able to accept a null value also
Related
For converting my GraphQL schema into Dart classes, I'm using the Ferry package, and I run this using build_runner.
In my database, I've defined the following enum type:
CREATE TYPE my_schm.currency AS ENUM ('CNY','EUR','PEN','USD');
Here is a translation of it (from schema.schema.gql.dart):
class GCurrency extends EnumClass {
const GCurrency._(String name) : super(name);
static const GCurrency CNY = _$gCurrencyCNY;
static const GCurrency EUR = _$gCurrencyEUR;
static const GCurrency PEN = _$gCurrencyPEN;
static const GCurrency USD = _$gCurrencyUSD;
static Serializer<GCurrency> get serializer => _$gCurrencySerializer;
static BuiltSet<GCurrency> get values => _$gCurrencyValues;
static GCurrency valueOf(String name) => _$gCurrencyValueOf(name);
}
This class, in turn, is used to:
class GCreateQuoteRequestVarsBuilder
implements
Builder<GCreateQuoteRequestVars, GCreateQuoteRequestVarsBuilder> {
_$GCreateQuoteRequestVars? _$v;
....
_i2.GCurrency? _currency;
_i2.GCurrency? get currency => _$this._currency;
set currency(_i2.GCurrency? currency) => _$this._currency = currency;
....
}
I am trying to implement the following request method (some variables have been omitted for clarity):
GCreateQuoteRequestReq createQuoteRequest(List<Object> values) => GCreateQuoteRequestReq(
(b) => b
..vars.vehicle = values[0] as String
..vars.body = values[1] as String
..vars.currency = values[5] as GCurrency
);
There is a problem with values[5], which is a String type, and I need to cast it to the right type, which should be GCurrency, but I'm getting this error:
The name 'GCurrency' isn't a type, so it can't be used in an 'as' expression.
Try changing the name to the name of an existing type, or creating a type with the name 'GCurrency'.
According to documentation I need to import the following files only for my tasks:
import '../loggedin.data.gql.dart';
import '../loggedin.req.gql.dart';
import '../loggedin.var.gql.dart';
You should be able to use the class GCurrency. Can you vars.currency = GCurrency.valueOf(values[5])?
I wanna serialize a json object including an ISOString date to a dart object using built value.
this is a sample json:
{
"title": "test",
"description": "test description",
"date": "2020-06-05T11:42:38.585Z",
"creator": {
"email": "test#test.com"
}
}
this is the model:
abstract class Post implements Built<Post, PostBuilder> {
#nullable
#BuiltValueField(wireName: '_id')
String get id;
String get title;
String get description;
DateTime get date;
#nullable
User get creator;
Post._();
static Serializer<Post> get serializer => _$postSerializer;
factory Post([updates(PostBuilder b)]) = _$Post;
factory Post.fromJson(Map<String, dynamic> map) =>
serializers.deserializeWith(Post.serializer, map);
Map<String, dynamic> toJson() =>
serializers.serializeWith(Post.serializer, this);
}
and this is the error:
Deserializing '[title, test1, description, test1 description, date, 2020-06-05T...' to
'Post' failed due to: Deserializing '2020-06-05T11:42:38.585Z' to 'DateTime' failed due
to: type 'String' is not a subtype of type 'int' in type cast
how do I fix that?
You can import the Iso8601DateTimeSerializer directly from built_value - don't copy the file over to your project.
Your final serializers.dart should look like:
import 'package:built_value/iso_8601_date_time_serializer.dart';
import 'package:built_value/iso_8601_duration_serializer.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
part 'serializers.g.dart';
#SerializersFor([
// your built value classes
])
final Serializers serializers = (_$serializers.toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Iso8601DurationSerializer())
..addPlugin(StandardJsonPlugin())
).build();
You need to add a custom DateTime serializer that you can find here: Iso8601DateTimeSerializer
create a new dart file (I named it iso8601_date_time_serializer.dart)
paste the code from 1
add the import to your serializers.dart file (import 'iso8601_date_time_serializer.dart';)
edit your serializers.g.dart file
Serializers _$serializers = (new Serializers().toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Post.serializer) // I assume you have this in yours
..addPlugin(StandardJsonPlugin()))
.build();
Please note that this modification might be deleted if you regenerate the code with build_runner.
In case you want to dig deeper, I got the answer from built_value GitHub issue 454
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.
I am programming a flutter app and have written dart class.
When I call the classes constructor, I the following error at runtime...
error: Instance field access outside constructor
The class looks as follows...
import '../framework/server.dart';
import 'package:meta/meta.dart';
class GamesRequestMessage extends Message {
String getName() => "GamesRequestMessage";
String idToken;
GamesRequestMessage({ #required this.idToken = idToken });
JsonObject content()
{
JsonObject content = JsonObject();
content.writeString("idToken" , idToken);
}
}
And the calling code where the error occurs is as follows...
var msg = GamesRequestMessage (idToken : idToken.token);
What has gone wrong? Also, why is this error not a compilation time error?
this.idToken = idToken should be just this.idToken
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.