Hilt trong ứng dụng nhiều mô-đun

Việc tạo mã Hilt cần quyền truy cập vào tất cả các mô-đun Gradle sử dụng Hilt. Mô-đun Gradle biên dịch lớp Application cần có tất cả các mô-đun Hilt và các lớp được chèn bằng hàm constructor (khởi tạo) trong các phần phụ thuộc bắt cầu của nó.

Nếu dự án nhiều mô-đun bao gồm các mô-đun Gradle thông thường, thì bạn có thể sử dụng Hilt theo mô tả trong bài viết Chèn phần phụ thuộc bằng Hilt. Tuy nhiên, phương pháp trên không dùng được cho các ứng dụng bao gồm nhiều mô-đun tính năng.

Hilt trong các mô-đun tính năng

Trong các mô-đun tính năng, cách mà các mô-đun thường phụ thuộc vào nhau thì tuân theo nguyên tắc dependency inversion (giảm thiểu sự phụ thuộc). Do đó, Hilt không thể xử lý các chú thích trong các mô-đun tính năng. Bạn phải sử dụng Dagger để chèn phần phụ thuộc vào các mô-đun tính năng của mình.

Bạn phải sử dụng các phần phụ thuộc thành phần để giải quyết vấn đề này với các mô-đun tính năng. Làm theo các bước sau:

  1. Khai báo giao diện @EntryPoint trong mô-đun app (hoặc trong bất kỳ mô-đun nào khác có thể được xử lý bằng Hilt) với các phần phụ thuộc mà mô-đun tính năng cần.
  2. Tạo một thành phần của Dagger phụ thuộc vào giao diện @EntryPoint.
  3. Sử dụng Dagger như bình thường trong mô-đun tính năng.

Hãy xem xét ví dụ trong trang Chèn phần phụ thuộc bằng Hilt. Giả sử bạn thêm một mô-đun tính năng login vào dự án. Bạn triển khai tính năng đăng nhập bằng một hoạt động có tên là LoginActivity. Có nghĩa là bạn chỉ có thể nhận được các liên kết từ thành phần của ứng dụng.

Đối với tính năng này, bạn cần một OkHttpClient với liên kết authInterceptor.

Trước tiên, hãy tạo giao diện @EntryPoint được cài đặt trong SingletonComponent với các liên kết mà mô-đun login cần:

Kotlin

// LoginModuleDependencies.kt - File in the app module.

@EntryPoint
@InstallIn(SingletonComponent::class)
interface LoginModuleDependencies {

  @AuthInterceptorOkHttpClient
  fun okHttpClient(): OkHttpClient
}

Java

// LoginModuleDependencies.java - File in the app module.

@EntryPoint
@InstallIn(SingletonComponent.class)
public interface LoginModuleDependencies {

  @AuthInterceptorOkHttpClient
  OkHttpClient okHttpClient();
}

Để thực hiện thao tác chèn trường trong LoginActivity, hãy tạo một thành phần Dagger phụ thuộc vào giao diện @EntryPoint:

Kotlin

// LoginComponent.kt - File in the login module.

@Component(dependencies = [LoginModuleDependencies::class])
interface LoginComponent {

  fun inject(activity: LoginActivity)

  @Component.Builder
  interface Builder {
    fun context(@BindsInstance context: Context): Builder
    fun appDependencies(loginModuleDependencies: LoginModuleDependencies): Builder
    fun build(): LoginComponent
  }
}

Java

// LoginComponent.java - File in the login module.

@Component(dependencies = LoginModuleDependencies.class)
public interface LoginComponent {

  void inject(LoginActivity loginActivity);

  @Component.Builder
  interface Builder {
    Builder context(@BindsInstance Context context);
    Builder appDependencies(LoginModuleDependencies loginModuleDependencies);
    LoginComponent build();
  }
}

Sau khi hoàn tất các bước này, hãy sử dụng Dagger như bình thường trong mô-đun tính năng của bạn. Chẳng hạn như bạn có thể sử dụng các liên kết từ SingletonComponent dưới dạng phần phụ thuộc của một lớp:

Kotlin

// LoginAnalyticsAdapter.kt - File in the login module.

class LoginAnalyticsAdapter @Inject constructor(
  @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
) { ... }

Java

// LoginAnalyticsAdapter.java - File in the login module.

public class LoginAnalyticsAdapter {

  private final OkHttpClient okHttpClient;

  @Inject
  LoginAnalyticsAdapter(
    @AuthInterceptorOkHttpClient OkHttpClient okHttpClient
  ) {
    this.okHttpClient = okHttpClient;
  }
  ...
}

Để thực hiện thao tác chèn trường, hãy tạo một phiên bản của thành phần Dagger bằng cách sử dụng applicationContext để lấy các phần phụ thuộc SingletonComponent:

Kotlin

// LoginActivity.kt - File in the login module.

class LoginActivity : AppCompatActivity() {

  @Inject
  lateinit var loginAnalyticsAdapter: LoginAnalyticsAdapter

  override fun onCreate(savedInstanceState: Bundle?) {
    DaggerLoginComponent.builder()
        .context(this)
        .appDependencies(
          EntryPointAccessors.fromApplication(
            applicationContext,
            LoginModuleDependencies::class.java
          )
        )
        .build()
        .inject(this)

    super.onCreate(savedInstanceState)
    ...
  }
}

Java

// LoginActivity.java - File in the login module.

public class LoginActivity extends AppCompatActivity {

  @Inject
  LoginAnalyticsAdapter loginAnalyticsAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    DaggerLoginComponent.builder()
        .context(this)
        .appDependencies(
          EntryPointAccessors.fromApplication(
            getApplicationContext(),
            LoginModuleDependencies.class
          )
        )
        .build()
        .inject(this);

    super.onCreate(savedInstanceState);
    ...
  }
}

Để biết thêm thông tin về các phần phụ thuộc của mô-đun trong các mô-đun tính năng, vui lòng xem phần Các phần phụ thuộc thành phần với các mô-đun tính năng.

Để biết thêm thông tin về Dagger trên Android, vui lòng xem phần Sử dụng Dagger trong các ứng dụng Android.