Flutter How To Use Injectable
Tags: flutter, mobile, programming, devjournal
Published: 2022-08-13 04:34:00

hi, before we start, this article are continue from preivous post regarding flutter mvvm using provider, injectable, and freeze


[MVVM Part 1](https://dev.to/noveriojoee/mvvm-with-flutter-52p6)
[MVVM Part 2](https://dev.to/noveriojoee/mvvm-with-flutter-part2freeze-48m9)
[The Code Project Is Here...](https://github.com/noveriojoee/what_to_do_app_flutter)


this article will focused on how to implement the injectable step by step...


now.. **[Injectable](https://pub.dev/packages/injectable#setup)**, are the **Dependency Injection** component that allow us to register an object to Dependency Injection through **Annotation**, instead of registering dependency with bellow approach

```
getIt.registerSingleton<TaskRepositoryImpl>(TaskRepositoryImpl());
getIt.registerLazySingleton<MainScreenViewModel>(() =>MainScreenViewModel());
```

we can simply put annotation on each class declaration of `TaskRepositoryImpl` and `MainScreenViewModel` like this

```
@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";
  
  ... 
}

@injectable
class MainScreenViewModel extends BaseViewModel {
  List<TaskModel>? _tasksData;

  final ITaskRepository _taskRepository = getIt<TaskRepositoryImpl>();

  ...
}
```

now in our case of ***[WhatToDoApp](https://github.com/noveriojoee/what_to_do_app_flutter)***
Remember This image? ![How ViewModel use Repository To Manage Many Model](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnaa367psh4uf5f9swap.png)
we'd like to have a singleton **Repository** and late assign of **ViewModel** layer... so we declare the `TaskRepository` this way : 
```
@singleton 
class TaskRepositoryImpl implements ITaskRepository{
  final String baseUrl = "run.mocky.io";
  
  ... 
}
```

and when we need to use it in the viewmodel we can use it this way

```
@injectable
class MainScreenViewModel extends BaseViewModel {
  List<TaskModel>? _tasksData;

//=== THIS WAY ===//
  final ITaskRepository _taskRepository = getIt<TaskRepositoryImpl>();

  ...
}
```

easy right?

no in order to implement this style, we need to import a couple things into our ***pubspec.yaml***
```
dependencies:
  flutter:
    sdk: flutter
  injectable: ^1.5.3
  get_it: ^7.2.0
dev_dependencies:
  # add the generator to your dev_dependencies
  injectable_generator: ^1.5.4
  # add build runner if not already added
  build_runner: ^2.2.0
```

remember, everytime we declare class with `@Injectable` or `@Singleton` annotation, the injectable component actually will generating file that contain a registration to [GetIt](https://pub.dev/packages/get_it) like bellow: 
```
_i1.GetIt $initGetIt(_i1.GetIt get,
    {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
  final gh = _i2.GetItHelper(get, environment, environmentFilter);
  gh.factory<_i3.MainScreenViewModel>(() => _i3.MainScreenViewModel());
  gh.singleton<_i4.TaskRepositoryImpl>(_i4.TaskRepositoryImpl());
  return get;
```

in order for injectable generating file content like above, you have to ***create some new file*** in my case it called ***Setup.dart*** 
and the content is like this.. 
```
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'package:what_to_do_app/Setup.config.dart';


final getIt = GetIt.instance;  
  
@InjectableInit(  
  initializerName: r'$initGetIt', // default  
  preferRelativeImports: true, // default  
  asExtension: false, // default  
)  

@InjectableInit(generateForDir: ['test'])  
void configureDependencies() => $initGetIt(getIt);  
```

after we declare the `Setup.dart` above, we can run command 
```
flutter packages pub run build_runner build --delete-conflicting-outputs
```
then it will generating file called `Setup.config.dart`. then that's it.. your Dependency Injection are now ready to serve you.. CHEERS!!!..

Ref: 
[Injectable](https://pub.dev/packages/injectable#setup)
[GetIt](https://pub.dev/packages/get_it)