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;
}
Related
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 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 wrote the following code using freezed with the intention of managing the loading state when the sign-in button is pressed on the sign-in page.
//sign_in_page_state.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
import 'package:state_notifier/state_notifier.dart';
part 'sign_in_page_state.freezed.dart';
#freezed
abstract class SignInPageState with _$SignInPageState {
const factory SignInPageState.noError() = _NoError;
const factory SignInPageState.error(String errorText) = _Error;
const factory SignInPageState.loading(String loadingText) = _Loading;
}
class SignInPageModel extends StateNotifier<SignInPageState>{
SignInPageModel(SignInPageState state):super(state);
void startSignIn(){
state=SignInPageState.loading("now signing in,please wait a minute.");
}
void successSignIn(){
state=SignInPageState.noError();
}
void errorSignIn(){
state=SignInPageState.error("failed to sign in.");
}
}
//signin_page.dart
class SignInPage extends StatefulWidget {
final String title = 'sign in';
static Widget create(BuildContext context,){
return StateNotifierProvider<SignInPageModel, SignInPageState>(
create:(_)=>SignInPageModel(SignInPageState.noError(),),
child:SignInPage(),
);
}
At this time, the following error will appear.
//error message
'SignInPageModel' doesn't conform to the bound 'StateNotifier<SignInPageState>' of the type parameter 'Controller'.
Try using a type that is or is a subclass of 'StateNotifier<SignInPageState>'.
No matter how I look at it, SignInPageModel is a subclass of StateNotifier<SignInPageState>.
and I also define and use UploadMovieState in much the same way as SignInPageState, but I don't get this error at all.
so I can't figure out the cause at all.
What could be the cause?
Since the State of SignInPage was declared as follows, it was caused by the same name 'SignInPageState'.
I'm sorry I asked a really silly question lol
class SignInPageState extends State<SignInPage> {
//...
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...
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