Problem with Dependency Injection and Get It in Flutter

1,581

getIt.registerFactory<MessageService>(() => EmailServiceImpl()); getIt.registerFactory<MessageService>(() => SMSServiceImpl());

GetIt only allows (by default) one instance of a type.

So your code is trying to register two instances of a same type (MessageService). From GetIt doc

You have to pass a factory function func that returns an NEW instance of an implementation of T. Each time you call get() you will get a new instance returned.

So when you call GetIt.I.get() it wont know if it's a EmailServiceImpl or a SMSServiceImpl

Try this

getIt.registerFactory<EmailServiceImpl>(() => EmailServiceImpl()); getIt.registerFactory<SMSServiceImpl>(() => SMSServiceImpl());

You can also allow reassingments so your code will work the way it is.

GetIt.I.allowReassignment = true

Share:
1,581
Shivam Singh
Author by

Shivam Singh

Updated on December 25, 2022

Comments

  • Shivam Singh
    Shivam Singh over 1 year

    I have been learning about Dependency Injection and now I have implemented an example in dart. But I'm facing an issue with get_it package. Here's the code:

    'MessageService.dart'

    abstract class MessageService {
      void sendMessage(String msg, String rec);
    }
    
    class EmailServiceImpl implements MessageService {
      @override
      void sendMessage(String message, String receiver) {
        //logic to send email
        print("Email sent to $receiver with message $message.");
      }
    }
    
    class SMSServiceImpl implements MessageService {
      @override
      void sendMessage(String message, String receiver) {
        //logic to send SMS
        print("SMS sent to $receiver with message $message.");
      }
    }
      
    

    'injection_container.dart'

    import 'package:get_it/get_it.dart';
    
    import 'MessageService.dart';
    import 'main.dart';
    
    final getIt = GetIt.instance;
    
    void init() async {
      getIt.registerFactory<Client>(() => Client());
      getIt.registerFactory<MyApplication>(() => MyApplication(EmailServiceImpl()));
      getIt.registerFactory<MessageService>(() => EmailServiceImpl());
      getIt.registerFactory<MessageService>(() => SMSServiceImpl());
    }
    

    'main.dart'

    import 'MessageService.dart';
    import 'injection_container.dart' as di;
    
    void main() {
      di.init();
      di.getIt<Client>().send();
    }
    
    class MyApplication {
      MessageService _service;
    
      MyApplication(this._service);
    
      void processMessages(String msg, String rec) {
        //do some msg validation, manipulation logic etc
        this._service.sendMessage(msg, rec);
      }
    }
    
    class Client {
      void send() {
        MyApplication app = di.getIt<MyApplication>();
        app.processMessages("Hi Bill", "[email protected]");
      }
    }
    

    But when registering both EmailServiceImpl and SMSServiceImpl in injection_container.dart it gives me in error as : Unhandled Exception: Invalid argument(s): Object/factory with type MessageService is already registered inside GetIt.

    If I comment out SMSServiceImpl registration it works fine. Can someone tell what's the problem? And it would be helpful if someone can review my Dependency Injection example. Is it the right way to present Dependency Injection?

    • Pieter van Loon
      Pieter van Loon over 3 years
      Why do you want to define both these services as MessageService in getit. How are you want to get one versus the other?
    • Shivam Singh
      Shivam Singh over 3 years
      I thought if we want to extend our application to provide/replace an additional messaging feature, such as SMS then we would just change it in the injector file. And getting dependency by above method is the only way i know. I don't know if it's the correct one. Please tell the correct one if it's not.
    • Shivam Singh
      Shivam Singh over 3 years
      The both services are defined as MessageService because MyApplication has a dependency of type MessageService. So you have to mention the type of those services. Hence MessageService is provided in get_it.
  • Shivam Singh
    Shivam Singh over 3 years
    Thanks for the answer.