I following a toturiel on how to use Data Class & Union in One Dart Package on Youtube
I come across this lines of code
#immutable
abstract class User with _$User {
const factory User(String name, int age) = _User;
}
don't under why he use this ' _$User "
and what is this line means
const factory User(String name, int age) = _User;
Please help and thank you
its an annotation from code-generators.
you can change _$User to _$Something and it will generate the same in partial file.
how to use and how it works depends on what code-generator package you used.
for more info
Related
I'm trying to build a union type for api responses.
I found freezed package supports union types and I tried out without issues. But as the api return different classes (responses) I think using a template type is suitable to keep the class as generic as possible.
This is the file I created:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'api_response.freezed.dart';
#freezed
class ApiResponse<T> with _$ApiResponse {
const factory ApiResponse.success(T content, String? message) = _Data;
const factory ApiResponse.failed(String? message, Object? exception) = _Error;
}
But when the build_runner generates the part file, there is an error on it:
Is there a way to fix it? Or another way to implement it?
Thanks in advance
It should work as follows:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'test_union.freezed.dart';
#freezed
class TestUnion<T> with _$TestUnion<T> {
const factory TestUnion.foo(T fubar) = _Foo<T>;
}
You can then use it as:
const foo = TestUnion<String>.foo("fubar");
So give this a go:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'api_response.freezed.dart';
#freezed
class ApiResponse<T> with _$ApiResponse<T> {
const factory ApiResponse.success(T content, String? message) = _Data<T>;
const factory ApiResponse.failed(String? message, Object? exception) = _Error;
}
I'm using https://pub.dev/packages/freezed to generate data classes with json.
I want to do this, so that I can use toJson() within the class.
class DatabaseRepository<T extends JsonSerializable> { ... }
But when I define the generic, I get the error: 'Prompt' doesn't conform to the bound 'JsonSerializable' of the type parameter 'T'. Try using a type that is or is a subclass of 'JsonSerializable'
Prompt is defined like so:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'prompt.freezed.dart';
part 'prompt.g.dart';
#freezed
class Prompt with _$Prompt {
const factory Prompt({
required String text,
String? id,
#Default(false) bool archived,
}) = _Prompt;
factory Prompt.fromJson(Map<String, dynamic> json) => _$PromptFromJson(json);
}
Is JsonSerializable the wrong class to extend? Or is this not possible to do?
I have just started learning freezed. I have a GameBase class below:
import 'package:json_annotation/json_annotation.dart';
part 'game_base.g.dart';
#JsonSerializable()
class GameBase {
final int id;
final String facilityName;
final ActivityType activityType;
final Level level;
final DateTime startTime;
final DateTime endTime;
final int participantsNumber;
final String admin;
const GameBase(
{required this.id,
required this.level,
required this.activityType,
required this.admin,
required this.startTime,
required this.facilityName,
required this.endTime,
required this.participantsNumber});
factory GameBase.fromJson(Map<String, dynamic> json) =>
_$GameBaseFromJson(json);
}
Now i have another class called Game, which extends from GameBase. I'm trying to use freezed on this class. I also have a getter in this class. Game class is shown bellow:
part 'game.freezed.dart';
part 'game.g.dart';
#freezed
class Game extends GameBase with _$Game {
Game._();
factory Game({
required List<UserBase> participants,
required String? gameDescription,
required String? activityGroundsName,
required DateTime day,
required double lat,
required double lng,
required int id,
required Level level,
required ActivityType activityType,
required String admin,
required DateTime startTime,
required String facilityName,
required DateTime endTime,
required int participantsNumber,
}) = _Game;
factory Game.fromJson(Map<String, dynamic> json) => _$GameFromJson(json);
get facilityActivityText {
if (activityGroundsName == null) {
return facilityName;
} else {
return facilityName + " - " + activityGroundsName!;
}
}
}
since I have a getter in this class, I must have a private custructor, as mentioned in freezed documentation. However, by doing so I get an error since I extend from GameBase and must call its costructor with its fields.
*Note: I know I can move one field up to GameBase and then have my getter over there without any issue, but since I've just started working with freezed I want to understand it better and find out if there's any way to handle this?
I think your problem's same as this thread. Hope this thread will answer ur questions.
Flutter/Dart: Subclass a freezed data class
I want to add private fields in Freezed data class.
So, I tried to write this.
#freezed
class User with _$User {
const factory User(
String _id,
String _name,
) = _User;
}
However, In my editor, displayed "Named parameters can't start with an underscore.(private_optional_parameter)" in user.freezed.dart
Please tell me what I solve this problem.
I have started learning bloc recently and I noticed some tutorials use multiple classes for states and others just use one class with multiple named constructors.
Example for multiple classes:
abstract class ProductsState {}
class ProductsInitial extends ProductsState {}
class ProductsLoading extends ProductsState {}
class ProductsSuccess extends ProductsState {
final List<Products> products;
ProductsSuccess(this.products);
}
class ProductsError extends ProductsState {
final String error;
ProductsError(this.error);
}
Example for multiple constructors:
enum AuthenticationStates {
initial,
success,
error,
}
class AuthenticationState {
final AuthenticationStates state;
final Authentication model;
final String msg;
const AuthenticationState._(
{this.state = AuthenticationStates.initial,
this.model,
this.msg = ''});
const AuthenticationState.initial() : this._();
const AuthenticationState.success(Authentication mdl)
: this._(model: mdl, state: AuthenticationStates.success);
const AuthenticationState.error(String m)
: this._(state: AuthenticationStates.error, msg: m);
}
Which one is better to use?
In my projects, I use the first way since different state types are clear, you can later build your UI based on that e.g. if (state is ProductsLoading) { show loader }.
You can also generate such classes by using the freezed package (https://pub.dev/packages/freezed). When using it, you would define a single class with different factory constructors (similar to your second option), but the generated code would support the first option you've defined, e.g.:
#freezed
class Union with _$Union {
const factory Union(int value) = Data;
const factory Union.loading() = Loading;
const factory Union.error([String message]) = ErrorDetails;
}
Later, in the UI layer, you could use helper methods like map/maybeMap/when/maybeWhen to build the corresponding view based on state, e.g.:
var union = Union(42);
print(
union.when(
(int value) => 'Data $data',
loading: () => 'loading',
error: (String? message) => 'Error: $message',
),
); // Data 42
I was asking myself the same question.
"The moment you check the concrete type of an instance in your logic, know you're not using polymorphism correctly." - Back in the university.
In the documentation of BloC they use one class with enum in all examples(or extra status class),
the enum will be composed of something similar to SUCCESS FAILURE etc.
Check the PostState mentioned in BloC documentation as example:
https://bloclibrary.dev/#/flutterinfinitelisttutorial?id=post-states
Nevertheless, the multiple sub-classes for state is a commonly used practice among flutter devs. It looks wrong for me, but who knows...