https://github.com/MinwooRowan/get_it_study
dependencies:
flutter:
sdk: flutter
get_it: ^8.0.2
injectable: ^2.5.0
injectable_generator: ^2.6.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
build_runner: ^2.4.13
final getIt = GetIt.instance;
void configureDependencies() => getIt.init();
GetIt
은 싱글톤 서비스 로케이터로, 전역 변수로 할당해 사용하기 쉽고, 프로젝트 내 여러 장소에서 동일한 인스턴스에 접근할 수 있다.원문 :
As Dart supports global (or euphemistic ambient) variables I often assign my GetIt instance to a global variable to make access to it as easy as possible.
Although the approach with a global variable worked well, it has its limitations if you want to use GetIt
across multiple packages. Therefore GetIt itself is a singleton and the default way to access an instance of GetIt
is to call:
getIt.init()
을 실행하는 함수 어노테이션에 @injectableInit
을 넣은 후 buill runner를 돌리면 동일한 디렉토리 위치에 config파일이 자동 생성된다.// 사용할때마다 새로운 인스턴스 발행
class Viewmodel {}
// 동일한 인스턴스 반환
class RepositoryImpl {}
// 동일한 인스턴스 반환하나, 처음 사용할때 초기화
class RepositoryImpl {}
final HomeViewmodel viewmodel = getIt<HomeViewmodel>();
return HomeScreen(viewmodel: viewmodel);
class HomeViewmodel extends ChangeNotifier {
HomeViewmodel({
required UserUsecase userUsecase,
required this.id,
}) : _userUsecase = userUsecase;
final UserUsecase _userUsecase;
final int id;
HomeViewmodel
은 파라미터로 UserUsecasd
와 id
를 받는다고 할때, @factoryParam
어노테이션이 붙은 파라미터는 아래처럼 받을 수 있게 된다.param
은 최대 2개 까지만 받을 수 있다.@factoryParam
은 당연히 @singleton
에는 사용할 수 없고, @injectable
에서만 사용가능final HomeViewmodel viewmodel = getIt<HomeViewmodel>(param1: 1);
@factoryParam
이 붙지않은 파라미터들은 getIt에서 자동으로 등록된 의존성들에서 검색하여 추가한다. 따라서 해당 파람들은 모두 getIt에 등록을 해야하고 안해두면 빌드에러가 발생한다. gh.factoryParam<_i205.HomeViewmodel, int, dynamic>((
id,
_,
) =>
_i205.HomeViewmodel(
userUsecase: gh<_i291.UserUsecase>(),
id: id,
));
class AppInit {
static Future<void> init() async {
WidgetsFlutterBinding.ensureInitialized();
configureDependencies();
logger.d('GET INITIALIZED');
}
}
// or @injectable
class HomeViewmodel extends ChangeNotifier {
HomeViewmodel({
required UserUsecase userUsecase,
}) : _userUsecase = userUsecase {
logger.d('HomeViewmodel INITIALIZED');
getUserList = Command0(_getUserList);
}
“GET INITIALIZED”
: 2024-12-11T10:12:48.25
”HomeViewmodel INITIALIZED”
: 2024-12-11T10:12:48.42
→ 0.2초
→ viewModel 사용될 때 초기화되는 것 확인
”HomeViewmodel INITIALIZED”
: 2024-12-11T10:15:22.712723
`“GET INITIALIZED”` **: 2024-12-11T10:15:22.721417**
→ Get It Initial될때 싱글톤 viewModel도 초기화되는 것 확인됨.
as
를 사용하여 어떤 클래스의 구현체인지 명시할 수 있다.abstract class UserRepository {}
(as: UserRepository)
class UserRepositoryImpl implements UserRepository {}
gh.lazySingleton<_i291.UserUsecase>(
() => _i291.UserUsecase(userRepository: gh<_i707.UserRepository>()));
('LocalImpl')
(as: UserRepository)
class UserLocalRepositoryImpl implements UserRepository {}
('RemoteImpl')
(as: UserRepository)
class UserRepositoryImpl implements UserRepository {}
class UserUsecase {
UserUsecase(('RemoteImpl') ARepository repository);
}
gh.lazySingleton<_i707.UserRepository>(
() => _i97.UserRepositoryImpl(userDatasource: gh<_i378.UserDatasource>()),
instanceName: 'LocalImpl',
dispose: (i) => i.dispose(),
);
gh.lazySingleton<_i707.UserRepository>(
() =>
_i97.UserRepositoryImpl2(userDatasource: gh<_i378.UserDatasource>()),
instanceName: 'RemoteImpl',
dispose: (i) => i.dispose(),
);
@factoryMethod
어노테이션을 기입한다. 함수명은 마음대로.class AsyncUserRepository {
static Future<AsyncUserRepository> create() async {
await Future.delayed(Duration(seconds: 2));
return AsyncUserRepository();
}
}
factoryAsync
로 불러오는 것을 확인할 수 있다.gh.factoryAsync<_i578.AsyncUserRepository>(
() => _i578.AsyncUserRepository.create());
getIt.getAsync
로 호출하여 사용final AsyncUserRepository repository = await getIt.getAsync<AsyncUserRepository>();
// or lazySingleton
class DataSource {
void dispose(){
}
}
void configureDependencies({String? environment}) =>
getIt.init(environment: environment);
class AppInit {
static Future<void> init() async {
configureDependencies(environment: 'dev');
}
}
(
as: UserRepository,
env: ['dev', 'qa'],
)
class UserRepositoryImpl implements UserRepository {}
(
as: UserRepository,
env: ['prod'],
)
class UserRepositoryImpl2 implements UserRepository {}
**const String _prod = 'prod';
const String _dev = 'dev';
const String _qa = 'qa';**
gh.factory<_i707.UserRepository>(
() =>
_i97.UserRepositoryImpl2(userDatasource: gh<_i378.UserDatasource>()),
instanceName: 'RemoteImpl',
registerFor: {**_prod**},
);
gh.lazySingleton<_i291.UserUsecase>(() => _i291.UserUsecase(
gh<_i707.UserRepository>(instanceName: 'RemoteImpl')));
gh.factory<_i707.UserRepository>(
() => _i97.UserRepositoryImpl(userDatasource: gh<_i378.UserDatasource>()),
instanceName: 'LocalImpl',
registerFor: {
**_dev,**
**_qa,**
},
);
https://pub.dev/packages/get_it
https://pub.dev/packages/injectable
https://orgeslayer.medium.com/flutter-di-get-it-injectable-624757613953
https://dev-yongsu.tistory.com/29
https://github.com/Milad-Akarie/injectable#disposing-of-singletons