Nguồn :
-
[get_it Dart Package](https://pub.dev/packages/get_it) - https://viblo.asia/p/flutter-dependency-injection-di-that-don-gian-voi-get-it-va-injectable-naQZRLkP5vx
- Giới thiệu
-
Package này hỗ trợ triển khai Dependency injection (DI)
-
InheritedWidget
-
Chúng ta có thể dùng widget này để triển khi DI. Nhưng nó có một số hạn chế :
-
Phải gắn trực tiếp vào UI
-
Dùng nhiều dependency thì bị lồng nhiều cấp.
-
Muốn truy cập một instance cần phải có context.
-
-
-
Get_it
ra đời để giải quyết các hạn chế trên.
-
Cài đặt
- Cách cài đặt giống các package khác nên mình không mô tả thêm.
-
Tạo các Instances
-
Factory : mỗi lần sử dụng các đối tượng sẽ tạo instance mới
// Dùng khi instance khởi tạo được ngay lập tức. getIt.registerFactory<HomeBloc>(() => HomeBloc()); // Dùng khi instance cần chạy bất đồng bộ để khởi tạo. getIt.registerFactoryAsync<HomeBloc>(() => HomeBloc.createAsync());
-
Singleton : Chỉ tạo một instance duy nhất
// Dùng khi instance có thể khởi tạo được ngay getIt.registerSingleton<CounterRepository>(CounterRepository()); // Dùng khi instance bắt buộc phải tạo dưới dạng bất đồng bộ (asynchronous) // hàm createAsync của CounterRepository trả về một Future<CounterRepository> getIt.registerSingletonAsync<CounterRepository>(() => CounterRepository.createAsync());
-
Lazy-singleton : Giống Singleton nhưng chỉ khởi tạo khi nó được dùng
getIt.registerLazySingleton<CounterRepository>(() => CounterRepository());
-
-
Sử dụng
-
getIt.get<T>()
: T là instance cần dùng. -
getIt.getAsync<T>()
: Dùng cho trường hợp bất đồng bộ
-
-
Giải quyết Dependency
-
A phụ thuộc B
class A { final B b; const A(this.b); } class B { }
// đăng kí B trước tiên getIt.registerSingleton<B>(B()); getIt.registerFactory<A>(() { // lấy object B bên trên... final b = getIt.get<B>(); // ...truyền vào constructor của A return A(b); });
-
A phụ thuôc async B
-
Lúc này phải chuyển contructor của A thành async, cụ thể :
-
registerFactoryAsync
thay vìregisterFactory
-
registerSingletonAsync
thay vìregisterSingleton
-
class A { final B b; const A(this.b); } class B { static Future<B> createAsync() { // ... khởi tạo B } }
// đăng kí B trước tiên getIt.registerSingletonAsync<B>(() => B.createAsync()); getIt.registerFactoryAsync<A>(() async { // chờ và lấy object B bên trên... final b = await getIt.getAsync<B>(); // ...truyền vào constructor của A return A(b); });
-
-
Async A phụ thuộc B
class A { final B b; const A(this.b); static Future<A> createAsync(B b) { // ... khởi tạo A } } class B { }
// đăng kí B trước tiên getIt.registerSingleton<B>(B()) getIt.registerFactoryAsync<A>(() async { // lấy object B bên trên... final b = getIt.get<B>(); // ...truyền vào hàm khởi tạo của A return await A.createAsync(b); });
-
Async A phụ thuộc Async B :
class A { final B b; const A(this.b); static Future<A> createAsync(B b) { // ... khởi tạo A } } class B { static Future<B> createAsync() { // ... khởi tạo B } }
// đăng kí B trước tiên getIt.registerSingletonAsync<B>(() => B.createAsync()) getIt.registerFactoryAsync<A>(() async { // lấy object B bên trên... final b = await getIt.getAsync<B>(); // ...truyền vào hàm khởi tạo của A return await A.createAsync(b); });
-
-
Truyền params vào factory
-
get_it hỗ trợ truyền tối đa 2 params
class User { final int age; final String name; const User({this.age, this.name}); }
// Khởi tạo getIt.registerFactoryParam<User, int, String>((age, name) => User(age: age, name: name));
getIt.get<User>(param1: 5, param2: 'Kevin');
- Nếu bạn muốn truyền nhiều hơn 2 params, có thể tạo một class đại diện cho các params và truyền vào như một param bình thường:
class UserParams { final int age; final String name; final String address; const UserParams({this.age, this.name, this.address}); } class User { final int age; final String name; final String address; const User({this.age, this.name, this.address}); User.withParams(UserParams params) : this(age: params.age, name: params.name, address: params.address); }
// Khởi tạo getIt.registerFactoryParam<User, UserParams>((params) => User.withParams(params));
// Sử dụng getIt.get<User>(param1: UserParams(age: 5, name: 'Kevin', address: 'Hanoi'));
-
-
Tự động đăng kí dependency với injectable
-
Hỗ trợ tự jnject thay vì phải tự khai báo
-
Cài đặt :
dependencies: ... injectable: ^1.0.4 dev_dependencies: ... injectable_generator: ^1.0.4 build_runner: ^1.10.2
- Bây giờ hãy mở file
injection.dart
, sửa lại thành như sau:
import 'package:get_it/get_it.dart'; import 'package:injectable/injectable.dart'; import 'injection.config.dart'; final getIt = GetIt.instance; @InjectableInit() Future<void> configureDependencies() async => await $initGetIt(getIt);
- Bạn sẽ thấy báo lỗi ở
import 'injection.config.dart';
và$initGetIt
.
flutter packages pub run build_runner build
- Nó sẽ tạo ra một file mơi :
injection.g.dart
tạo bởi injectable nằm cùng vị trí vớiinjection.dart
- Bây giờ hãy mở file
-
Sử dụng :
- Giờ thì thay vì chúng ta viết mọi thứ ở trong
configureDependencies()
,hãy tạm quên nó đi và chuyển qua object bạn cần khởi tạo. Giả sử mình có 2 class A và B, mình muốn thêm nó vào DI dưới dạng factory, A phụ thuộc vào B thì mình chỉ cần import và thêm annotation@injectable
phía trên 2 class đó
import 'package:injectable/injectable.dart'; @injectable class A { final B b; const A(this.b); } @injectable class B { }
- Giờ thì thay vì chúng ta viết mọi thứ ở trong
-
Thực hiện tạo file
// GENERATED CODE - DO NOT MODIFY BY HAND // ************************************************************************** // InjectableConfigGenerator // ************************************************************************** import 'package:get_it/get_it.dart'; import 'package:injectable/injectable.dart'; import 'models.dart'; /// adds generated dependencies /// to the provided [GetIt] instance GetIt $initGetIt( GetIt get, { String environment, EnvironmentFilter environmentFilter, }) { final gh = GetItHelper(get, environment, environmentFilter); gh.factory<B>(() => B()); gh.factory<A>(() => A(get<B>())); return get; }
-