Cuộc chiến giữa Compile-time và Runtime
Việc chọn giữa Hilt và Koin là quyết định quan trọng nhất khi thiết kế kiến trúc ứng dụng. Dù cùng giải quyết bài toán Dependency Injection, chúng lại đi theo hai triết lý hoàn toàn trái ngược. Hãy khám phá và tìm ra công cụ phù hợp nhất cho dự án của bạn.
1. Decision Engine
Phần này giúp bạn tính toán xem Hilt hay Koin phù hợp hơn dựa trên các đặc tả dự án thực tế của bạn. Chọn các tiêu chí bên dưới để xem kết quả đánh giá tự động.
Cấu hình dự án của bạn
Mức độ phù hợp
Radar Chart
Biểu đồ phân tích 5 khía cạnh cốt lõi của hai thư viện. Hilt chiếm ưu thế tuyệt đối về sự an toàn do phát hiện lỗi ngay lúc biên dịch (Compile-time), trong khi Koin tỏa sáng ở khả năng hỗ trợ Đa nền tảng (KMP) và tốc độ biên dịch mã nguồn cực nhanh do không phải sinh code tự động.
- Hilt: DI thực sự, mạnh mẽ, nhưng phức tạp và build chậm.
- Koin: Service Locator, gọn nhẹ, viết bằng DSL, dễ crash runtime nếu quên config.
2. Hành trình Chuyển đổi: Từ Koin sang Hilt
Khám phá cách tư duy thay đổi từ Runtime DSL (Koin) sang Compile-time Annotations (Hilt). Phần này hiển thị các ví dụ mã nguồn thực tế và đối chiếu sự khác biệt. Hãy chọn các tab bên dưới để xem cách thay đổi mã nguồn.
dependencies {
implementation("io.insert-koin:koin-android:3.x.x")
}
plugins {
id("dagger.hilt.android.plugin")
id("com.google.devtools.ksp")
}
dependencies {
implementation("com.google.dagger:hilt-android:2.51")
ksp("com.google.dagger:hilt-android-compiler:2.51")
}
3. Koin có gây ra lỗi ANR?
Nhiều nhà phát triển cho rằng dùng Koin làm ứng dụng bị treo (Application Not Responding) hơn Hilt do tính chất phân giải lúc Runtime. Tuy nhiên, sự thật có phải như vậy? Phần này phân tích nguyên nhân gốc rễ và đưa ra giải pháp.
Kết luận nhanh
Koin KHÔNG trực tiếp gây ra ANR nhiều hơn Hilt. Tuy nhiên, ở các dự án có hàng ngàn dependency, việc tra cứu HashMap lúc khởi chạy (startKoin) tốn CPU hơn, có thể làm rớt khung hình (Jank) hoặc làm chậm Cold Start (vài mili-giây).
ANR (App treo > 5 giây) thường do sai lầm kinh điển của lập trình viên: Làm tác vụ I/O nặng bên trong hàm khởi tạo.
❌ Nguyên nhân thực sự gây Crash
Dù dùng Hilt hay Koin, nếu bạn đặt tác vụ đọc Database/File vào block init, Main Thread sẽ bị chặn cứng khi DI framework khởi tạo class đó.
class UserRepository(private val database: AppDatabase) {
init {
// LỖI NGHIÊM TRỌNG: Query Database trên Main Thread
// Khi DI khởi tạo class này, App sẽ bị treo!
val data = database.userDao().getAllUsersSync()
}
}
✅ Cách phòng tránh an toàn
- Tuyệt đối không đọc/ghi dữ liệu nặng ở Constructor hoặc block `init`.
- Khởi tạo đối tượng rỗng/nhẹ nhàng, sau đó dùng
Coroutines (Dispatchers.IO)để lấy dữ liệu bất đồng bộ. - Nếu dùng Koin, hạn chế dùng
createdAtStart = truecho các module không quan trọng để giảm tải lúc App vừa mở.