About errors in state management using freezed and StateNotifier in Flutter - flutter

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> {
//...

Related

unable to register an abstract class in using injectable and get_it packages

I'm using injectable and get_it in flutter dart (following the very popular Reso coder)
I have a simple abstract class:
import 'package:injectable/injectable.dart';
//#injectable
abstract class IRandomQuantityRepository {
Future<int> getRandomQuantity();
}
and I have two simple concrete implementations of it:
import 'package:injectable/injectable.dart';
#dev
#injectable
class DevRandomQuantityRepository implements IRandomQuantityRepository {
const DevRandomQuantityRepository();
#override
Future<int> getRandomQuantity() async => 90;
}
and
import 'dart:math';
import 'package:injectable/injectable.dart';
#prod
#injectable
class RandomQuantityRepository implements IRandomQuantityRepository {
const RandomQuantityRepository();
#override
Future<int> getRandomQuantity() async => Random().nextInt(100);
}
Lastly, I have an injection.dart:
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'package:moontreeapp/injection.config.dart';
final GetIt getIt = GetIt.instance;
#InjectableInit(preferRelativeImports: false)
void configureInjection(String env) {
$initGetIt(getIt, environment: env);
}
abstract class Env {
static const prod = 'prod';
static const dev = 'dev';
}
besides all that I have a bloc that wants to use stuff:
#injectable
class RandomQuantityBloc
extends Bloc<RandomQuantityEvent, RandomQuantityState> {
final IRandomQuantityRepository _quantityFacade; // notice this final...
doesn't that look good? I think so. So then I run this command to make the generated code flutter pub run build_runner watch
But I get a message:
[RandomQuantityBloc] depends on unregistered type [IRandomQuantityRepository]... Did you forget to annotate the above class(s) or their implementation with #injectable?
or add the right environment keys?
Ok, so that's cool, lets add it to the interface:
import 'package:injectable/injectable.dart';
#injectable // <-- added
abstract class IRandomQuantityRepository {
Future<int> getRandomQuantity();
}
but then I get a new error:
> [IRandomQuantityRepository] is abstract and can not be registered directly!
> if it has a factory or a create method annotate it with #factoryMethod
> 14 │ abstract class IRandomQuantityRepository {
> │ ^^^^^^^^^^^^^^^^^^^^^^^^^
In the past I've handled dependency injection manually, so I'm new to these packages, what am I missing here?
Besides all that, the real issue is that I can't switch the injection based on the environment. I can use get_it to get a concrete dependency but not one based on environment like in this test:
/// has no effect:
configureInjection(Env.dev);
/// gets prod version:
final devRandomQuantity = getIt<RandomQuantityRepository>();
So something about this whole set up isn't configuring the Injections correctly... What am I missing?
One final thing that might be useful is to see the generated code:
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// InjectableConfigGenerator
// **************************************************************************
import 'package:get_it/get_it.dart' as _i1;
import 'package:injectable/injectable.dart' as _i2;
import 'package:moontreeapp/application/quantity/bloc/randomquantity_bloc.dart'
as _i5;
import 'package:moontreeapp/domain/quantity/i_randomquantity_repository.dart' as _i6;
import 'package:moontreeapp/infrastructure/quantity/dev_randomquantity_repository.dart'
as _i3;
import 'package:moontreeapp/infrastructure/quantity/mock_randomquantity_repository.dart'
as _i4;
import 'package:moontreeapp/infrastructure/quantity/randomquantity_repository.dart'
as _i7;
const String _dev = 'dev';
const String _prod = 'prod';
// ignore_for_file: unnecessary_lambdas
// ignore_for_file: lines_longer_than_80_chars
/// initializes the registration of provided dependencies inside of [GetIt]
_i1.GetIt $initGetIt(_i1.GetIt get,
{String? environment, _i2.EnvironmentFilter? environmentFilter}) {
final gh = _i2.GetItHelper(get, environment, environmentFilter);
gh.factory<_i3.DevRandomQuantityRepository>(
() => _i3.DevRandomQuantityRepository(),
registerFor: {_dev});
gh.factory<_i5.RandomQuantityBloc>(
() => _i5.RandomQuantityBloc(get<_i6.IRandomQuantityRepository>()));
gh.factory<_i7.RandomQuantityRepository>(() => _i7.RandomQuantityRepository(),
registerFor: {_prod});
return get;
}
Do I put #injectable on abstract classes or not?
ok, so I guess injectable can't see what the class implements so you have to make it explicit. also, I missed that #dev isn't built in, you have to make it.
So this is the proper way to use the decorations
#Environment('dev')
#Injectable(as: IRandomQuantityRepository)
class DevRandomQuantityRepository implements IRandomQuantityRepository {
const DevRandomQuantityRepository();
#override
Future<Either<QuantFailure, Quantity>> getRandomQuantity() async =>
right(Quantity(Amount(900.0001), Decimal(4)));
}
and that way this does work:
configureInjection(Env.dev);
final mockRandomQuantity = getIt<IRandomQuantityRepository>();
await mockRandomQuantity.getRandomQuantity();
// 90

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

How to use Freezed package with Bloc in flutter?

I want to create a simple bloc with freezed package. This is my bloc:
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:presentation/presentation_index.dart';
part 'auth_bloc_event.dart';
part 'auth_bloc_state.dart';
class AuthBlocBloc extends Bloc<AuthEvent, AuthState> {
final SignUpBuyerUseCase signUpBuyerUseCase;
AuthBlocBloc(this.signUpBuyerUseCase) : super(AuthState.initial());
#override
Stream<AuthState> mapEventToState(
AuthEvent event,
) async* {
yield* event.map();
}
}
and my event class :
part of 'auth_bloc.dart';
#freezed
abstract class AuthEvent with _$AuthEvent {
const factory AuthEvent.login(String username, String password) = Login;
const factory AuthEvent.signUpBuyer(BuyerEntity entity) = SignUpBuyer;
}
and state class :
part of 'auth_bloc.dart';
#freezed
abstract class AuthState with _$AuthState {
const factory AuthState.initial() = InitialAuthState;
const factory AuthState.signUpBuyerFail(String error) = SignUpBuyerFail;
const factory AuthState.signUpBuyerSuccess() = SignUpBuyerSuccess;
const factory AuthState.signUpBuyerLoading() = SignUpBuyerLoading;
}
The problem is that when i try to run
flutter pub run build_runner watch --deleteonflicting-outputs
Nothing happens and no classes are generated
In the bloc, you should try to include the freezed file.
part 'auth_bloc_event.dart';
part 'auth_bloc_state.dart';
part 'auth_bloc.freezed.dart';

Multiple questions related to Flutter basic

I am coming from React and trying to understand Flutter. There are some differences between dart vs JS and React vs Flutter. However, it seems a bit similar to each other. However, there is some confusion toward Flutter.
void
It does not return the value. Therefore, it is used to void main(). Does it mean like the function 'main()' will be executed and I will never be able to reuse void main()?
<>
In the code, I have here
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
class LoginScreenState extends State<LoginScreen> {
Widget build(context) {
return Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: [
emailField(),
// passwordField(),
// submitButton(),
],
));
}
}
I can see that State<LoginScreen> is related to class LoginScreen. It is an extension of the LoginScreen State?
Future<int> successor = future.then((int value) {
},
However, in here Future <----- I do not understand why it has to state 'int' in this code. What is the proper use of <>?
Stateful vs Stateless
Can I just use the Stateful all the time even if I do not have any state like React? Where there is no difference?
You need to learn basic dart.
void main() is same as main(). The only difference is declaring the return type. main() is called only once by the flutter engine.
Read about generics. <> is the called the diamond operator and is used to specify the type of something. Future<int> means the function will return something in future and it will strictly be of int type. If you don't specify the type flutter will treat it as dynamic.
You can use stateful classes if you are using state management packages like provider or rxdart to maintain state.
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
enter code here
changed to
class LoginScreen extends StatefulWidget {
LoginScreenState createState()=>LoginScreenState();
}
}
enter code here
Stateful vs Stateless`enter code here`
stateful has state object and stateless has no state object.using stateful you can changes widget data .on other hand in stateful you cant

How to access it's static constant from instance of an object?

I have an object that has static constant which I need to reach from its instance.
class ChatsScreen extends StatefulWidget {
var arguments;
static const name = ADatas.chatRoute;
ChatsScreen(this.arguments);
createState() => ChatsScreenState();
}
In above class' State object, I want to call static const name. Above class' State object's code:
class ChatsScreenState extends State<ChatsScreen> with RouteHelper{
String userName = "";
var textEditingController = TextEditingController();
#override
void initState() {
getRouteName(widget); //=> as I understand and see on the VSCode, its the ChatsScreen object.
super.initState();
}
}
I'm trying to implement an interface so I don't know the actually class name while writing the interface. And I thought that I can reach its static constant if I know its actual class. And I wrote something like this but it seems not to be possible. I guess I have a misunderstanding.
class RouteHelper{
String getRouteName(dynamic instance){
if(instance is StatefulWidget){
return instance.runtimeType.name; // => !!!
}
}
}
Note: I'm not trying to get the route name in actual. It's just a concept that i used in this question, so please don't refer better way to get the route name in flutter.
You can't do it like that, people have talked about this in this issue.
However you can kinda do it using class members and typing system.
abstract class Routed {
String getClassRoute();
}
class ChatsScreen extends StatefulWidget implements Routed {
var arguments;
static const name = "myexampleroutename";
ChatsScreen(this.arguments);
createState() => ChatsScreenState();
#override
String getClassRoute() {
return ChatsScreen.name;
}
}
class RouteHelper {
String getRouteName(Routed instance) {
return instance.getClassRoute();
}
}
I said you can't, but with dart:mirrors it is possible, however it is banned on Flutter packages. There is reflectable package that tries to fix that using code generation, but I am not aware of it's status/reliability.