Một vài lưu ý nhanh đối với Dagger 2
Bài đăng này đã không được cập nhật trong 5 năm
Nếu bạn biết cách sử dụng Dagger 2
nhưng đôi khi quên cú pháp hoặc một số cách dùng cơ bản của nó. Thì hy vọng bài viết này sẽ là một nơi hỗ trợ bạn.
Và nếu bạn đang muốn học Dagger 2
từ đầu, thì dưới đây sẽ phù hợp hơn, nhưng trong bài viết này tôi sẽ làm cho nó rất đơn giản. Để mọi người cùng hiểu Dagger
là gì.
Những thành phần cơ bản
Nào chúng ta cùng bắt đầu với các thành phần cơ bản.
@Component
Trong Dagger 2, phần quan trọng nhất là Component
. Về cơ bản, nó là một đối tượng (sẽ được tạo tự động) để xử lý tất cả nội dung dependency injection
của bạn.
Để định nghĩa một Component
. Bạn có thể viết theo như dưới đây
@Component
interface FirstComponent
Bạn có thể tạo nó, ở bất cứ nơi nào trong code của bạn, sau đó bạn có thể gọi (bằng tiền tố với Dagger
)
DaggerFirstComponent.create()
@Inject
Các thành phần không làm gì cho đến khi bạn sử dụng nó để giúp injection
của bạn. Bạn cần nói cho nó biết đối tượng mục tiêu mà nó cần injection
vào.
@Component
interface FirstComponent{
fun inject(object: Target)
}
Với điều này, nó có thể inject
bất kỳ lớp nào có chú thích(annotation) @Inject
trong hàm tạo của nó. ví dụ.
class DependentClass @Inject constructor()
@Scope
Ngoài ra, đối với mỗi component
, bạn có thể chú thích scope
, ví dụ:
chú thích @Singleton
bên dưới :
@Singleton
@Component
interface FirstComponent{
fun inject(object: Target)
}
Điều này cho phép mọi đối tượng phụ thuộc (dependent object injected
) được chèn bởi thành phần này, có @Scope
phù hợp sẽ chỉ được tạo một lần trong phạm vi (scope) đó. ví dụ.
@Singleton
class DependentClass @Inject constructor()
Để khai báo custom scope
, người ta cần xác định một tên chú thích mới.
@Scope
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class CustomScope
@Module
(và@Provides
)
Tuy nhiên, nếu người ta muốn đóng gói tất cả các Lớp phụ thuộc liên quan (Dependents Classes) lại với nhau. Thì chúng ta có thể định nghĩa nó trong một module.
Và Component
có thể liên kết với module
dưới dạng một injection
của nó.
@Module
class FirstModule {
@Provides
fun getDependentDependentObject() = DependentDependentClass()
@Singleton
@Provides
fun getDependentObject(
dependentDependentObject: DependentDependentClass)
= DependentClass(dependentDependentObject)
}
@Singleton
@Component(modules = [FirstModule::class])
interface FirstComponent {
fun inject(object: Target)
}
Giả sử nếu bạn muốn inject
một DependentObject
bằng cách thủ công, Bạn có thể đặt nó làm tham số của hàm tạo (contructor) giống như class FirstModule
như sau.
@Module
class FirstModule(
val dependentDependentObject: DependentDependentClass) {
@Singleton
@Provides
fun getDependentObject()
= DependentClass(dependentDependentObject)
}
Nếu như thế này thì bạn không thể sử dụng được các hàm như bên dưới nữa
DaggerFirstComponent.create() // Không thể dùng được nữa.
Thay vào đó bạn cần phải làm theo như bên dưới.
DaggerFirstComponent.builder().setFirstModule(
FirstModule(dependentDependentObject)).build()
Nếu bạn muốn thứ gì đó tốt hơn nữa khi tạo Component
mà không cần truy cập Module
, hãy xem theo Link bên dưới
Component.Builder
Một số thành phần khác
@Subcomponent
@Subcomponent
có thể được xem như là một phần tử con của @Component
. Để có hướng dẫn đơn giản nhưng đầy đủ về nó, bạn có thể tham khảo ở đây
Subcomponent
Ở đây tôi cung cấp cách liên kết @Subcomponent
với @Component
@Singleton
@Component(modules = [FirstModule::class])
interface FirstComponent {
fun getSubcomponent(): FirstSubcomponent
}
@SubScope
@Subcomponent(modules = [FirstSubmodule::class])
interface FirstSubcomponent {
fun inject(object: Target)
}
Với điều này, việc tạo FirstComponent
vẫn có thể đơn giản
val firstComponent = DaggerFirstComponent.create()
Nhưng để truy cập vào subcomponent
val firstSubcomponent = firstComponent.getSubComponent()
Subcomponent
có quyền truy cập vào biến của Component
cha cũng như các Module
Có điều mà các bạn cần lưu ý :
Component
vàSubcomponent
của cùng mộtScope
thì không thể được liên kết, trừ khi cả hai đều không cùngScope
@Component
dependencies
Bên cạnh việc có @SubComponent
. Thì Component
có thể phụ thuộc vào Component
khác. Điều này có thể thực hiện như bên dưới đây :
@Singleton
@Component(modules = [FirstModule::class])
interface FirstComponent {
fun inject(object: FirstTarget)
}
@AnotherScope
@Component(dependencies = [FirstComponent::class],
modules = [SecondModule::class])
interface SecondComponent {
fun inject(object: SecondTarget)
}
Với các dòng code bên trên. Để tạo FirstComponent
Nó chỉ đơn giản gọi.
val firstComponent = DaggerFirstComponent.create()
Nhưng để tạo ra SecondComponent
chúng ta phải đảm bảo rằng FirstComponent
phải được inject
vào nó
DaggerSecondComponent.builder()
.firstComponent(firstComponent).build()
Tham khảo sơ đồ bên trên, thì khả năng truy cập vào các phụ thuộc (dependencies
) từ SubComponent
thì giống với FirstComponent
Subcomponent
khả năng truy cập đầy đủ của parent Component
(bao gồm các Module
), Trong khi các phụ thuộc thành phần (component dependencies
) chỉ có khả năng truy cập vào immediate dependent
chứ không phải module
.
Giống như lưu ý của Subcomponent
Các @Component có cùng scope sẽ không thể liên với nhau. Trừ khi cả hai không nằm trong phạm vi.
Tổng kết
Hy vọng bạn đã hiểu đầy đủ tất cả những điều trên. Cảm ơn các bạn đã đọc bài viết này.
All rights reserved