I need to understand this code, resoCoder did it on DDD Playlist. why does he implements IEntity inside freezed?
The code is:
#freezed
abstract class TodoItem with _$TodoItem implements IEntity {
const factory TodoItem({
#required UniqueId id,
#required TodoName name,
#required bool done,
}) = _TodoItem;
factory TodoItem.empty() => TodoItem(
id: UniqueId(),
name: TodoName(''),
done: false,
);
}
}
IEntity code is:
abstract class IEntity {
UniqueId get id;
}
UniqueId Code is:
class UniqueId extends ValueObject<String> {
#override
final Either<ValueFailure<String>, String> value;
// We cannot let a simple String be passed in. This would allow for possible non-unique IDs.
factory UniqueId() {
return UniqueId._(
right(Uuid().v1()),
);
}
/// Used with strings we trust are unique, such as database IDs.
factory UniqueId.fromUniqueString(String uniqueIdStr) {
assert(uniqueIdStr != null);
return UniqueId._(
right(uniqueIdStr),
);
}
const UniqueId._(this.value);
}
It ensures consistency; TodoItem must implement everything as per IEntity.
Let's imagine one day you want to add an attribute "createdAt" to IEntity: in this case, you will have to add "createdAt" to every class that implements IEntity across the project, otherwise the compiler will let you know you're missing something :D
Some code now.
The result would be
abstract class IEntity {
UniqueId get id;
int get createdAt; // let's keep it "int" for the example purpose
}
then you would have to update the freezed class too
#freezed
abstract class TodoItem with _$TodoItem implements IEntity {
const factory TodoItem({
#required UniqueId id,
#required int createdAt,
#required TodoName name,
#required bool done,
}) = _TodoItem;
factory TodoItem.empty() => TodoItem(
id: UniqueId(),
createdAt: 1234,
name: TodoName(''),
done: false,
);
}
}
Related
I am still a beginner with BLoC architecture. So far the UI updates when using int, bool, and other basic data types. But when it comes to Maps it really confuses me. My code basically looks like this:
my state
enum TalentStatus { initial, loading, loaded, error }
class TalentState extends Equatable {
const TalentState({
required this.talentStatus,
this.selectedService = const {},
required this.talents,
this.test = 0,
});
final TalentStatus talentStatus;
final Talents talents;
final Map<String, Service> selectedService;
final int test;
TalentState copyWith({
TalentStatus? talentStatus,
Talents? talents,
Map<String, Service>? selectedService,
int? test,
}) =>
TalentState(
selectedService: selectedService ?? this.selectedService,
talentStatus: talentStatus ?? this.talentStatus,
talents: talents ?? this.talents,
test: test ?? this.test,
);
#override
List<Object> get props => [talentStatus, talents, selectedService, test];
}
my event
abstract class TalentEvent extends Equatable {
const TalentEvent();
#override
List<Object> get props => [];
}
class TalentStarted extends TalentEvent {}
class TalentSelectService extends TalentEvent {
const TalentSelectService(
this.service,
this.talentName,
);
final Service service;
final String talentName;
}
and my bloc
class TalentBloc extends Bloc<TalentEvent, TalentState> {
TalentBloc(this._talentRepository)
: super(TalentState(
talentStatus: TalentStatus.initial, talents: Talents())) {
on<TalentSelectService>(_selectService);
}
final TalentRepository _talentRepository;
Future<void> _selectService(
TalentSelectService event,
Emitter<TalentState> emit,
) async {
state.selectedService[event.talentName] = event.service;
final selectedService = Map<String, Service>.of(state.selectedService);
emit(
state.copyWith(
selectedService: selectedService,
),
);
}
}
whenever an event TalentSelectService is called BlocBuilder doesn't trigger, what's wrong with my code?
Your Service object must be comparable. One suggestion is that it extends Equatable. Either way it have to implement (override) the == operator and hashCode
The reason your BlocBuilder doesn't trigger is (probably) that it doesn't recognize that there has been a change in the Map.
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 am very new to Dart and Flutter, and I've been trying to make two classes (SuccessState and ErrorState) that implement an abstract class (DataState) with optional named parameters. For some reason, whenever I call the super constructor in SuccessState and ErrorState, I get an undefined_named_parameter error on the "data" parameter in the SuccessState constructor and "status" and "msg" parameters in the ErrorState constructor. Any input is greatly appreciated, thanks.
abstract class DataState<T> {
final T? data;
final int? status;
final String? msg;
const DataState({this.data, this.status, this.msg});
}
class SuccessState<T> implements DataState<T> {
const SuccessState(T data) : super(data: data);
#override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class ErrorState<T> implements DataState<T> {
const ErrorState(int status, String msg) : super(status: status, msg: msg);
#override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
You want to extend SuccessState and ErrorState to DataState.
abstract class DataState<T> {
final T? data;
final int? status;
final String? msg;
const DataState({this.data, this.status, this.msg});
}
class SuccessState<T> extends DataState<T> {
SuccessState(T data) : super(data: data);
#override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class ErrorState<T> implements DataState<T> {
const ErrorState(int status, String msg) : super();
#override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
The problem is you are using implements rather than extends. You don't inherit the super constructor when using implements.
The thing you are doing wrong is your are implementing as you have to extend DataState class then issue will resolved
'class ErrorState implements DataState'
Change to class ErrorState extends DataState
how can I use groupBy function which is in collection.dart to group items by two fields and return a model class with them not one field like int?
If I group by one field, It works fine and there is no problem:
Map<int, List<FooterItem>> _getGroups(List<FooterItem> items) {
return groupBy(items, (FooterItem i) {
return i.groupId;
});
}
But when I wan to return a model class from result ,groupBy is not grouping values .
here I have a list of FooterItem which has It's group data and how can I use groupBy to group a List<FooterItem> by groupId and titleGroup and return FooterGroup not int :
class FooterItem {
final int id;//item id
final int groupId;
final String title;//item title
final String titleGroup;
...
}
Map<FooterGroup, List<FooterItem>> _getGroups(List<FooterItem> items) {
return groupBy(items, (FooterItem i) {
return FooterGroup(id: i.groupId, title: i.titleGroup);
});
}
I could solve problem by extending Equatable in the model class which I wanted to use as grouped values and overriding props :
import 'package:equatable/equatable.dart';
class FooterGroup extends Equatable{
final int id;
final String title;
FooterGroup({
#required this.id,
#required this.title,
});
#override
List<Object> get props => [id,title];
}
so duplicate values of Groups where not seen any more. so
Map<FooterGroup, List<FooterItem>> _getGroups(List<FooterItem> items) {
return groupBy(items, (FooterItem i) {
return FooterGroup(id: i.groupId, title: i.titleGroup);
});
}
works fine now.
A quick way to achieve this:
groupBy(footers, (FooterItem f) {
return '${f.groupId}+${f.titleGroup}';
});
Source: https://coflutter.com/dart-how-to-group-items-in-a-list/
I'm having a hard time understanding how to use the package for base cases like describing API requests/responses. I might be stuck in a loop where I've got something in mind and I'm trying to make it work at all costs that way, and I can't see simpler solutions.
Example:
#freezed
abstract class BaseRequest with _$BaseRequest {
const factory BaseRequest({
#required int a,
#required String b,
}) = _BaseRequest;
}
#freezed
abstract class BaseResponse with _$BaseResponse {
const factory BaseResponse({
#required bool c,
}) = _BaseResponse;
}
then
#freezed
abstract class Authentication with _$Authentication {
#Implements(BaseRequest)
const factory Authentication.request({
#required int a,
#required String b,
#required String psw,
}) = _AuthenticationRequest;
#Implements(BaseResponse)
const factory Authentication.response({
#required bool c,
#required String token,
}) = _AuthenticationResponse;
factory Authentication.fromJson(Map<String, dynamic> json) =>
_$AuthenticationFromJson(json);
}
There's something smelly there and I'm sure I'm missing something and I'm not able to properly compose those classes.
Might Freezed even be overkill in this case?
You cannot implement/extend Freezed classes.
Either change your BaseResponse/BaseRequest to:
abstract class BaseRequest {
int get a;
String get b;
}
abstract class BaseResponse{
bool get c;
}
or use composition instead of inheritance:
#freezed
abstract class Authentication with _$Authentication {
const factory Authentication.request({
#required BaseRequest request,
#required String psw,
}) = _AuthenticationRequest;
const factory Authentication.response({
#required BaseResponse response,
#required String token,
}) = _AuthenticationResponse;
}