Skip to content

ResetLazySingleton is not resetting. #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
petermusembi69 opened this issue Apr 8, 2021 · 25 comments
Closed

ResetLazySingleton is not resetting. #170

petermusembi69 opened this issue Apr 8, 2021 · 25 comments

Comments

@petermusembi69
Copy link

petermusembi69 commented Apr 8, 2021

Hello there,
I am implementing a login feature using getIt and cubit. So once the user clicks on the login button the desired behaviour is to reset the lazySingleton Logincubit. This is necessary when the login credentials are wrong. The app should be able to restart the auth process afresh.

I am using get_it: ^6.0.0

Here is where I add the resetLazySingleton in the UI in the BlocConsumer

   return BlocConsumer<LogInCubit, LogInState>(
            listener: (context, state) => state.when(
                  initial: () {},
                  loading: () {},
                  loaded: () {
                    Navigator.pushNamed(
                      context,
                      AppRouter.otpRoute,
                    );
                  },
                  error: (error) {
                    phoneNumberController.clear();
                    passwordController.clear();
                    locator.resetLazySingleton<LogInCubit>();
                  },
                ),

and the Login button.

@override
 Widget build(BuildContext context) {
   final l10n = context.l10n;
   return MaterialButton(
     onPressed: () {
       locator<LogInCubit>().logIn(
         phoneNumber: phoneNumberController,
         password: passwordController,
       );
       locator.resetLazySingleton<LogInCubit>();
     },

Here is where I register my LazySingleton

GetIt locator = GetIt.instance;

void setUpServiceLocator() {
 // Services
 locator
   ..registerLazySingleton<LogInCubit>(
     () => LogInCubit(
       authService: locator(),
       hiveService: locator(),
     ),
@saharvx9
Copy link

There is bug in get_it_impl class
look for function : _findFirstFactoryByInstanceOrNull
then change this from:

    final registeredFactories =
         _allFactories.where((x) => identical(x.instance, instance));

to :

final registeredFactories =
         _allFactories.where((x) => identical(x.registrationType, instance));

registrationType will do the magic

@escamoteur
Copy link
Collaborator

@saharvx9 That's not correct. That part of the code is absolutely correct.

@petermusembi69 I just looked at the code. How do you know it didn't reset?

@escamoteur
Copy link
Collaborator

@saharvx9 a bit more explanation. The function you want to change is only called when you pass an instance of an Object which @petermusembi69 doesn't do here. If you needed to make the change that you proposed to get your code working you are using resetLazySinglteton wrong. you can't pass a type as instance. if you don't have an isntance, pass the type as with all other methods as generic parameter

@escamoteur
Copy link
Collaborator

@petermusembi69 just a tip, for situations like that I recommend to check if get_it scopes wouldn't be the better way to go.

@saharvx9
Copy link

@saharvx9 That's not correct. That part of the code is absolutely correct.

@petermusembi69 I just looked at the code. How do you know it didn't reset?

I check dozen of times instance is always null
So this is why its not possible to to reset it with this line, when i change it it worked perfectly

@escamoteur
Copy link
Collaborator

if instance is null _findFactoryByInstance isn't called as you can see

 @override
  void resetLazySingleton<T extends Object>({
    Object? instance,
    String? instanceName,
    void Function(T)? disposingFunction,
  }) {
    _ServiceFactory instanceFactory;

    if (instance != null) {
      instanceFactory = _findFactoryByInstance(instance);
    } else {
      instanceFactory = _findFactoryByNameAndType<T>(instanceName);

@escamoteur
Copy link
Collaborator

couly you show me the line whare you call resetLazySingelton?

@petermusembi69
Copy link
Author

@saharvx9 That's not correct. That part of the code is absolutely correct.

@petermusembi69 I just looked at the code. How do you know it didn't reset?

@saharvx9's approach doesn't help much.

@escamoteur this is how I know it didn't reset. Here are the cubit logs, thrown when the app is running. I have 4 states(initial, loading, loaded, error).

1st try with wrong LogIn credentials.

[log] onChange(LogInCubit, Change { currentState: LogInState.initial(), nextState: LogInState.loading() })
[log] onChange(LogInCubit, Change { currentState: LogInState.loading(), nextState: LogInState.error(message: Login Failed!) })

2nd try with the correct credentials starts off with the error state. This should not be the case if the lazySignleton was reset. It should start with the initial state instead.

[log] onChange(LogInCubit, Change { currentState: LogInState.error(message: Login Failed!), nextState: LogInState.loading() })
[log] onChange(LogInCubit, Change { currentState: LogInState.loading(), nextState: LogInState.error(message: Login Failed!) })

3rd try with the correct credentials

[log] onChange(LogInCubit, Change { currentState: LogInState.error(message: Login Failed!), nextState: LogInState.loading() })
[log] onChange(LogInCubit, Change { currentState: LogInState.loading(), nextState: LogInState.error(message: Login Failed!) })

@petermusembi69
Copy link
Author

petermusembi69 commented Apr 12, 2021

couly you show me the line whare you call resetLazySingelton?

locator.resetLazySingleton<LogInCubit>();
@escamoteur you metioned something about "pass the type as with all other methods as generic parameter". I think that is what I have done here. If not, kindly explain further.

@escamoteur
Copy link
Collaborator

@petermusembi69 can it be that you have somewhere else a reference to this Cubit so that the garbage collector can't do its job? I'm not familiar with Cubit but AFAIK it used streams, so you will have to call some dispose method on the cubid or not?

@escamoteur
Copy link
Collaborator

@escamoteur you metioned something about "pass the type as with all other methods as generic parameter". I think that is what I have done here. If not, kindly explain further.
No, you do it exactly as it should be

@escamoteur
Copy link
Collaborator

could you solve your problem?

@petermusembi69
Copy link
Author

@escamoteur Not yet, I will have a look at it, in the course of the week and share any useful findings.

@petermusembi69
Copy link
Author

@petermusembi69 can it be that you have somewhere else a reference to this Cubit so that the garbage collector can't do its job? I'm not familiar with Cubit but AFAIK it used streams, so you will have to call some dispose method on the cubid or not?

Cubit is a high-level library and it extends dart streams in the background. Using BlocProvider will automatically dispose the cubit.

@kmartins
Copy link
Contributor

kmartins commented May 4, 2021

@escamoteur I have the same problem here but in the version 7.0.0. In the version, 6.0.0 is working normally.

@kmartins
Copy link
Contributor

kmartins commented May 4, 2021

try this small test - Version: 7.0.0

class Value {
  int number = 0;
}

GetIt.I.registerLazySingleton<Value>(() => Value());
final value = GetIt.I.get<Value>();
value.number = 10;
print(value.number); // 10 - OK
GetIt.I.resetLazySingleton<Value>(instance: value);
final value2 = GetIt.I.get<Value>();
print(value2.number); // 10 instead of 0

@escamoteur
Copy link
Collaborator

oh, sorry you now have to await the reset

@escamoteur
Copy link
Collaborator

I recommend checking out the changelog

@kmartins
Copy link
Contributor

kmartins commented May 4, 2021

OK, It's working 👍🏾
Thanks.

@kmartins
Copy link
Contributor

kmartins commented May 5, 2021

However, if I do not have a disposing function in my resetLazySingleton, why I must have to use await?

I think changing this in the functions resetLazySingleton and unregister, works better

In resetLazySingleton

if (instanceFactory.instance! = null) {
       if (disposingFunction! = null) {
         await disposingFunction.call (instanceFactory.instance as T);
       } else {
         await instanceFactory.dispose ();
       }
     }

to:

if (instanceFactory.instance != null) {
      if (disposingFunction != null) {
        final dispose = disposingFunction.call(instanceFactory.instance as T);
        if (dispose is Future) {
          await dispose;
        }
      } else {
        final dispose = instanceFactory.dispose();
        if (dispose is Future) {
          await dispose;
        }
      }
}

@escamoteur
Copy link
Collaborator

Hmm, that's an interesting take honestly I hadn't thought about that possibility. Would you like to make a PR and add tests to secure that it works as it should?

@kmartins
Copy link
Contributor

kmartins commented May 5, 2021

OK, I created a pull request -> #185

@escamoteur
Copy link
Collaborator

Just pushed V7.1.2

@petermusembi69 could you please check if this version still has the problem for you?

@petermusembi69
Copy link
Author

@escamoteur Version V7.1.2 solved the problem. I was able to get the desired behaviour from the cubit as shown in the logs below. Thank you.

[log] onChange(LogInCubit, Change { currentState: LogInState.initial(), nextState: LogInState.loading() })
[log] onChange(LogInCubit, Change { currentState: LogInState.loading(), nextState: LogInState.error(message: The selected phone number is invalid.) })
[log] onChange(LogInCubit, Change { currentState: LogInState.initial(), nextState: LogInState.loading() })
[log] onChange(LogInCubit, Change { currentState: LogInState.loading(), nextState: LogInState.loaded() })

@ddthanh198
Copy link

I await the reset the reset, but does not work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants