Flutter - Freezed package - How to properly compose classes - flutter

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;
}

Related

Freezed The argument type 'RequestWithFailureState<dynamic>' cant be assigned to the parameter type 'RequestWithFailureState<Fragment$LovelyUserData>'

I imagine i'm doing something wrong here but cant seem to figure it out.
I have a set of nested freezed states, starting from the highest:
#freezed
class DataDemoViewControllerState with _$DataDemoViewControllerState {
const factory DataDemoViewControllerState({
required final RequestWithFailureState<Fragment$LovelyUserData>
updatePhoneNumberStatus,
}) = _DataDemoViewControllerState;
}
#freezed
class RequestWithFailureState<D> with _$RequestWithFailureState<D> {
const factory RequestWithFailureState() = _Initial;
const factory RequestWithFailureState.loading() = _Loading;
const factory RequestWithFailureState.failed(DomainRequestFailure failure) =
_Failed;
const factory RequestWithFailureState.success(D data) = _Success<D>;
}
#freezed
class DomainRequestFailure
with _$DomainRequestFailure
implements DomainFailure {
const factory DomainRequestFailure.unknown([String? message]) =
_UnknownRequestFailure;
const factory DomainRequestFailure.network(String message) =
_NetworkRequestFailure;
const factory DomainRequestFailure.notConnected() =
_NotConnectedRequestFailure;
const factory DomainRequestFailure.unauthorized(
{required DomainReAuthFailure reAuthFailure,
required String message}) = _UnauthorizedRequestFailure;
}
However I get an error for the top level .freezed file: data_demo_view_controller_state.freezed.dart
The argument type 'RequestWithFailureState<dynamic>' can't be assigned to the parameter type 'RequestWithFailureState<Fragment$LovelyUserData>'
The error occurs at the value assignment inside data_demo_view_controller_state.freezed.dart at:
#override
$RequestWithFailureStateCopyWith<dynamic, $Res> get updatePhoneNumberStatus {
return $RequestWithFailureStateCopyWith<dynamic, $Res>(
_value.updatePhoneNumberStatus, (value) {
return _then(_value.copyWith(updatePhoneNumberStatus: value));
});
}
Im likely missing something obvious but just cant see it. Any help at all would be amazing. Thank you.
Edit:
This does seem to work with:
#freezed
class DataDemoViewControllerState<M> with _$DataDemoViewControllerState<M> {
const factory DataDemoViewControllerState(
{#Default(RequestWithFailureState())
RequestWithFailureState<M> updatePhoneNumberStatus}) =
_DataDemoViewControllerState<M>;
And passing in the generic, but not optimal.

how to use freezed on a class with custome function that inherits from a non-sealed class in dart?

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

when to implements an abstract class in freezed?

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,
);
}
}

How to define proper state class in bloc while using freezed plugin

I am trying to understand, how can I use the bloc pattern (specifically state) properly. I am facing this issue for more than a month, but not able to figure out a solution.
Let's consider, I have defined state class following way,
#freezed
abstract class ExampleState with _$ExampleState {
const factory ExampleState.initial() = Initial;
const factory ExampleState.getDataFromServer() = GetDataFromServer; //Thsi will return the ServerData Object.
const factory ExampleState.useServerData() = UseServerData;
const factory ExampleState.changeServerDataAndUpload() = ChangeServerDataAndUpload;
}
Let's consider our Server Data Model is the following way
class ServerData {
final String userId;
final String firstName;
final String lastName;
final String fullAddress;
final String fatherName;
ServerData(
this.userId,
this.firstName,
this.lastName,
this.fullAddress,
this.fatherName,
);
}
In this example, we are able to see, GetDataFromServer, UseServerData, and ChangeServerDataAndUpload state is sharing the same ServerData object. How should I design my state such that, the same DataModel object can be shared between different states?

How to avoid repetition in Flutter while using JsonSerialzable

I have models that I need to map them to JSON and vice versa. Therefore, I've followed flutter's JSON and serialization guide on how to do so.
I found myself writing the same code base for each model, like so:
import 'package:flutter/material.dart';
import 'package:json_annotation/json_annotation.dart';
part 'folder_entity.g.dart';
#JsonSerializable(explicitToJson: true)
class FolderEntity {
final String id;
final String path;
bool isSelected;
FolderEntity({
#required this.id,
#required this.path,
this.isSelected = false,
});
factory FolderEntity.fromMap(Map<String, dynamic> json) => _$FolderEntityFromJson(json);
Map<String, dynamic> toMap() => _$FolderEntityToJson(this);
}
I thought about moving fromMap and toMap to a new abstract class called Entity, but I'm unable to do so for two reasons:
I can't extend a factory, therefore I have write the same pattern for each method.
I'm not sure if there's an option to change prefix from _$FolderEntity to just _$Entity, and if would still be available, will it even work?
For second question you should be change prefix from _$FolderEntity to just _$Entity in folder_entity.g.dart file.