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 6 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 ý :
Có điều mà các bạn cần lưu ý :
ComponentvàSubcomponentcủa cùng mộtScopethì 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 (
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
 
  
 