Goodbye Dagger, Hello Koin
Bài đăng này đã không được cập nhật trong 6 năm
source: https://raw.githubusercontent.com/ekito/koin/master/img/banner_2000.png
Giới thiệu
Hiện tại nhắc tới dependency injection khi dev app Android thì đa phần chúng ta sẽ đều nghĩ ngay tới Dagger 2
Về cơ bản khi cài đặt Dagger cho Android chúng ta sẽ cần định nghĩa đơn giản như sau:
class MainApplication : DaggerApplication()
interface AppComponent : AndroidInjector<MainApplication> { }
class NetworkModule { }
class AppModule { }
class ActivityModule { }
class FragmenModule { }
class ViewModelModule { }
Dagger hiện tại ổn định và mạnh mẽ tuy nhiên nó quá phức tạp, quá nhiều code lặp lại và hơn nữa khi dùng Dagger sẽ có thêm nhiều file code được tự động gen. Nếu bạn dùng Dagger với Data binding thì số code gen ra sẽ rất nhiều. Khi đó việc debug đôi khi là ác mộng.
Chính ví thế nên mình nghĩ liệu chúng ta có nên thử xem qua Koin khi mà gần đây Koin đã chính thức ra bản 1.0.0.
Koin là gì?
Koin là một lightweight dependency injection framework được viết bằng Kotlin và cho Kotlin, giải pháp bằng funtional nên không sinh code, không ánh xạ.
Cài đặt
Version hiện tại
koin_version = '1.0.0'
Gradle
Jcenter
repositories {
jcenter()
}
Dependencies
Core
// Koin for Kotlin
implementation "org.koin:koin-core:$koin_version"
Android
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
// Koin Android ViewModel feature
implementation "org.koin:koin-android-viewmodel:$koin_version"
Cơ bản về Koin DSL
- module { } - tạo một Koin Module hoặc một submodule (ở trong một module khác)
- factory { } - cung cấp một newInstance
- single { } - cung cấp một singleton
- get() - yêu cầu component
- bind - thêm định nghĩa về kiểu cho đối tượng
- getProperty() - yêu cầu property
Về cơ bản chúng ta sẽ dùng module, factory, single, get.
Chi tiết hơn thì các bạn xem ở link này https://insert-koin.io/docs/1.0/quick-references/koin-dsl/
Code nào
Khai báo Koin module
val networkModule = module{
single { createOkHttpCache(get()) } // create singleton, get() for component dependency
single { createLoggingInterceptor() } // create singleton
}
fun createOkHttpCache(context: Context): Cache {
val size = (10 * 1024 * 1024).toLong() // 10 Mb
return Cache(context.cacheDir, size)
}
fun createLoggingInterceptor(): Interceptor {
val logging = HttpLoggingInterceptor()
logging.level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY
else HttpLoggingInterceptor.Level.NONE
return logging
}
val viewModelModule = module {
// viewModel { } create viewModel
// get() for component dependency
viewModel { PopularMovieViewModel(get(), get()) }
// new way
viewModel<PopularMovieViewModel>()
}
class PopularMovieViewModel constructor(
val movieRepository: MovieRepository,
val movieDao: MovieDao
) : VideModel()
Start Koin
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin(this, listOf(
appModule,
networkModule,
repositoryModule,
viewModelModule
))
}
}
Inject trong Android
val viewModelModule = module {
viewModel { PopularMovieViewModel(get(), get()) }
// new way
viewModel<PopularMovieViewModel>()
}
class PopularMovieViewModel constructor(
val movieRepository: MovieRepository,
val movieDao: MovieDao // inject in constructor
) : VideModel() {
// or lazy inject
val movieDao: MovieDao by inject()
// or directly get
val movieDao : MovieDao = get()
}
class PopularMovieFragment : Fragment() {
// lazy inject
val viewModel by viewModel<PopularMovieViewModel>()
// or directly get
val viewModel : PopularMovieViewModel = viewModel()
// or directly get
val viewModel getViewModel<PopularMovieViewModel>()
// share viewModel between fragment and activity
val viewModel by sharedViewModel<MainActivityViewModel>()
}
Như vậy là chúng ta đã setup xong dependency injection bằng Koin. Thật đơn giản phải không nào!
Đây là link pull request mình thực hiện chuyển từ Dagger sang Koin các bạn có thể tham khảo:
https://github.com/dangquanuet/The-Movie-DB-Kotlin/pull/60
So sánh một chút
Lí do nên chuyển từ Dagger sang Koin
- Dependencies ít hơn
- Code ngắn gọn
- Ít code sinh ra
- Dễ hiểu và cài đặt
- Hỗ trợ properties
- Build time nhanh hơn
- Chính thức 1.0.0
Dagger còn tốt hơn Koin ở?
- Dagger thực hiện trong compile time nên nếu có lỗi dependency thì sẽ phát hiện sớm
- Chỉ cần @Inject là có thể inject
- Koin hãn còn mới
Sau những gì mình đã giới thiệu thì các bạn hãy tự mình khám phá và quyết định xem có nên chuyển hẳn sang Koin không nhé.
Xin chào và hẹn gặp lại các bạn!
Tham khảo
https://github.com/InsertKoinIO/koin
https://proandroiddev.com/london-tube-status-app-from-dagger-to-koin-17f96dbf8e0b
https://medium.com/@shinoogoyalaggarwal/koin-a-dependency-injection-framework-85ed1eb2eaa5
All rights reserved