[Dart/Flutter]Add private fileds in Freezed data class - flutter

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.

Related

Union class with template type

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

final model properties in flutter

in the flutter when you are defining a model. the convention is to define properties as final and write a copyWith for class instead of defining non-final vars and removing the copyWith method. what is the exact reason for this? is it a flutter performance thing?
for example:
class Emplyee {
final String name;
final String id;
Emplyee({required this.name, required this.id});
Emplyee copyWith({String? name, String? id}) {
return Emplyee(id: id ?? this.id, name: name ?? this.name);
}
Map<String, dynamic> toJson() => {
"name": name,
"id": id,
};
Emplyee.fromJson(Map<String, dynamic> json)
: name = json["name"],
id = json["id"];
}
P.S. I know this convention makes sense in widgets. but my question is about data model classes.
It's for Immutability. Mutable class is error-prone.
So basically the copyWith method makes it possible for you to create a new instance of the class and then you can edit whatever you want in this new instance of the class, without affecting data in the original class.
So that's what the copyWith method does, I don't think it's for performance, I think it just aids some coding use cases.
Immutability reduces the risk of errors by side effects. Have a look at this code:
class User {
String name;
User({required this.name});
}
void main() {
final user = User(name: 'Stefan');
someFunction(user);
print(user.name);
}
someFunction(User user){
user.name = 'Thomas';
}
This snippet prints 'Thomas' because the function manipulates the user object. In the main function, you have no chance to know what happens with the object.
With immutability, this would not be possible. It would be necessary to create a new instance of User to have a User named 'Thomas'. The instance in the main function would be the same.
Using final makes a class immutable.
You can check Why do we need immutable class?
Immutable class is good for caching purpose and it is thread safe.
The reason behind using copyWith() is flexible, allowing any number of properties to be updated in a single call.
More about immutable-data-patterns-in-dart-and-flutter

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?

Flutter: When should the factory constructor be used?

https://flutter.dev/docs/cookbook/networking/fetch-data
In the last 'complete example' of the above page,
class Album {
final int userId;
final int id;
final String title;
Album({this.userId, this.id, this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
It is an Album class to receive the JSON string received in the request and handle it in the application,
The constructor provides a factory constructor in addition to the normal constructor.
About the factory constructor,
https://dart.dev/guides/language/language-tour#constructors
I have read the Factory constructors section of the above page.
The factory constructor of the Logger class in the sample does not always create a new instance, so
I can understand adding the factory keyword,
Is it necessary to use the factory constructor even in the Album class of this Complete example?
In the case of the Album class, since the normal constructor is used in the factory constructor,
I feel that this factory constructor (Album.fromJson) always creates a new instance.
In fact
Future<Album> fetchAlbum() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/albums/16');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var temp=json.decode(response.body);
return Album(userId:temp['userId'],id:temp['id'],title:temp['title']);
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
As you can see, it seems that it works without any problems even if I try using only the normal constructor.
Is there any advantage to preparing and using a factory constructor?
Or is there something wrong without using the factory constructor in this situation?
I'm not sure when to use the factory constructor in the first place,
Is there a clear definition?
Before diving into factory as keyword in flutter, you might have a look at Factory as design pattern to have the full picture in mind.
The main benefit of using factory design pattern
That is, the Factory Method design pattern defines an interface for a class responsible for creating an object, hence deferring the instantiation to specific classes implementing this interface. This resolves the issue of creating objects directly within the class which uses them.
Also, it enables compile-time flexibility via subclassing. When objects are created within the class, it is very inflexible since you cannot change the instantiation of the object independently from the class — the class is committed to a particular object. By implementing the pattern, subclasses can be written to redefine the way an object is created.
For more info, see here
and as docs refers
Use the factory keyword when implementing a constructor that doesn’t always create a new instance of its class. For example, a factory constructor might return an instance from a cache, or it might return an instance of a subtype. Another use case for factory constructors is initializing a final variable using logic that can’t be handled in the initializer list.
So it's all about hiding the creation logic from outside world.
And of course you can do the following
return Album(userId:temp['userId'],id:temp['id'],title:temp['title']);
But if you did that in many different components or classes let's say, so whenever you change the logic behind the creation of Album object you will be in-need to change it over all places.
On the other hand the classes which use Album class they only care about having an Object of Album, they care not about how it got instantiated, so if you put the logic of having an instance outside the class itself you are going into what's called spaghetti code
You can use factory to test for example if the json data returned by som request is null so you return a null dirctly by the use of factory named constructor for example look at this
//class for Product, Brand, Model
class PBM {
static const String pbmCollectionName = 'productsBrandsModels';
static const String pbmIdField = 'pbmId';
static const String pbmNameField = 'pbmName';
static const String parentIdField = 'parentId';
static const String iconUrlField = 'iconUrl';
//general
final String pbmId;
final String pbmName;
final String parentId;
//icon
final String iconUrl;
PBM({
this.pbmId,
this.pbmName,
this.parentId,
this.iconUrl,
});
Map<String, dynamic> toMap() {
return {
'pbmId': pbmId,
'pbmName': pbmName,
'parentId': parentId,
'iconUrl': iconUrl,
};
} //end of toMap method
factory PBM.fromFirestore(Map<String, dynamic> firestore) {
//here the benefit of factory comes into play: it will return a null
//otherwise it gonna create the object
if (firestore == null) return null;
return PBM(
pbmId: firestore['pbmId'],
pbmName: firestore['pbmName'],
parentId: firestore['parentId'],
iconUrl: firestore['iconUrl'],
);
} //end of PBM.fromFirestore named constructor
} //end of PBM class

Abstract Class with mixin dart flutter

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