Dependency Injection trong flutter (part 2)

Trần Đình Quý

Part 1: https://dev.tora-tech.com/dependency-injection-trong-flutter-part-1/

Giải quyết dependency

Có những trường hợp object A cần cung cấp object B mới có thể hoạt động (A depends on B), vậy thì chúng ta sẽ phải làm như nào?

Factory/singleton A phụ thuộc vào factory/singleton 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);
});

Factory/singleton A phụ thuộc vào asynchronous factory/singleton B

Lúc này phải chuyển hàm khởi tạo A thành asynchronous chứ không còn dùng được synchronous nữa, cụ thể là phải dùng:

  • 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);
});

Asynchronous factory/singleton A phụ thuộc vào factory/singleton B

Phần này cũng khá giống với Factory/singleton A phụ thuộc vào factory/singleton 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);
});

Asynchronous factory/singleton A phụ thuộc vào asynchronous factory/singleton B

Phần này cũng khá giống với Factory/singleton A phụ thuộc vào asynchronous factory/singleton 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);
});

Tự động đăng kí dependency với Injectable

Cơ chế inject dependency chỉ cần thêm annotation trên đầu class cần inject và nó sẽ tự động tìm và inject luôn cho mình chứ không phải declare ra như bên trên.

Ta cần 2 plugin là build_runner và injectable để thực hiện điều này

Cài đặt

Đầu tiên chúng ta cần thêm vào pubspec.yaml, chạy flutter packages get để cài đặt.

https://pub.dev/packages/build_runner

https://pub.dev/packages/injectable

https://pub.dev/packages/injectable_generator

dependencies:
    ...
    injectable: ^1.0.4

dev_dependencies:
    ...
    injectable_generator: ^1.0.4
    build_runner: ^1.10.2

Sửa file injection_container.dart thành như sau:

import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';

import 'injection_container.config.dart';

final sl = GetIt.instance;

@InjectableInit()  
void configureDependencies() => sl.init();  

Chạy lệnh sau để fix các lỗi xuất hiện

flutter packages pub run build_runner build

Giờ quay lại với các phụ thuộc và thêm vào @injectable

@injectable  
class NumBloc {  
    //...
}  

Tất nhiên ngoài factory ra, chúng ta cũng có thể dùng singleton và lazy-singleton bằng các annotation @singleton và @lazySingleton.

Với asynchronous factory bạn có thể dùng @injectable trên class và @factoryMethod trên hàm khởi tạo như sau:

import 'package:injectable/injectable.dart';

@injectable
class A {
    @factoryMethod
    static Future<A> createAsync() {
        //...
    }
}

Kết

Với các dự án trung bình và lớn thì Dependency Injection là một thứ không thể thiếu để bảo đảm tính dễ dàng maintain và scalable của dự án. Việc sử dụng đem lại rất nhiều lợi ích và việc áp dụng DI vào dự án sẽ giúp bạn nâng trình độ code của mình lên rất nhiều.

Hãy chia sẻ cho mọi người cùng biết để mở rộng kiến thức hơn nhé 😄

Viết một bình luận