一、基础配置与概念
1. 什么是 appModule
appModule
是 Koin 依赖注入框架中的核心配置模块,用于集中管理应用中的所有依赖项。它本质上是一个 Koin 模块(org.koin.core.module.Module
),通过 DSL 方式声明各种组件的创建方式和依赖关系。
2. 基本结构
kotlin
val appModule = module {
// 在这里声明各种依赖项
single { } // 单例组件
factory { } // 每次创建新实例
viewModel { } // ViewModel组件
}
二、完整配置示例
1. 基础配置(app/build.gradle)
gradle
dependencies {
// Koin 核心
implementation "io.insert-koin:koin-core:3.4.3"
implementation "io.insert-koin:koin-android:3.4.3"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
// 协程
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
}
2. 完整 appModule 示例
kotlin
// di/KoinModules.kt
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val appModule = module {
// 1. 单例组件
single {
SharedPreferencesManager(
androidContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
)
}
// 2. 带接口绑定的Repository
single<UserRepository> { UserRepositoryImpl(get()) }
// 3. ViewModel
viewModel { MainViewModel(get(), get()) }
// 4. 带参数的ViewModel
viewModel { (userId: String) ->
UserDetailViewModel(userId, get())
}
// 5. 网络服务
single {
Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
// 6. 协程Dispatcher
single(named("IO")) { Dispatchers.IO }
single(named("Main")) { Dispatchers.Main }
}
三、实战应用
1. Application 初始化
kotlin
// MyApp.kt
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApp)
modules(appModule)
// 调试日志
if (BuildConfig.DEBUG) {
androidLogger(Level.DEBUG)
}
}
}
}
2. 在 Activity 中使用
kotlin
class MainActivity : AppCompatActivity() {
// 普通ViewModel注入
private val mainViewModel: MainViewModel by viewModel()
// 带参数的ViewModel
private val userViewModel: UserDetailViewModel by viewModel {
parametersOf(intent.getStringExtra("USER_ID") ?: "")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 直接使用已注入的ViewModel
mainViewModel.loadData()
}
}
3. 在 Fragment 中使用
kotlin
class UserFragment : Fragment() {
// 共享Activity的ViewModel
private val sharedViewModel: MainViewModel by sharedViewModel()
// 本Fragment独有的ViewModel
private val userViewModel: UserViewModel by viewModel()
}
四、高级用法
1. 多模块组织
kotlin
// di/modules/
val networkModule = module {
single { createOkHttpClient() }
single { createRetrofit(get()) }
single { get<Retrofit>().create(ApiService::class.java) }
}
val databaseModule = module {
single { createDatabase(androidContext()) }
single { get<AppDatabase>().userDao() }
}
val repositoryModule = module {
single<UserRepository> { UserRepositoryImpl(get(), get()) }
}
val viewModelModule = module {
viewModel { MainViewModel(get()) }
}
2. 作用域控制
kotlin
val sessionModule = module {
// 用户会话期间有效的作用域
scope(named("SessionScope")) {
scoped { UserSessionManager(get()) }
}
}
// 使用
class LoginActivity : AppCompatActivity() {
private val sessionScope = getKoin().createScope("user_session", named("SessionScope"))
private val sessionManager: UserSessionManager by inject()
override fun onDestroy() {
sessionScope.close()
super.onDestroy()
}
}
3. 属性注入
kotlin
val configModule = module {
single {
AppConfig(
apiUrl = getProperty("API_URL", "https://default.api"),
timeout = getProperty("TIMEOUT_MS", 5000L)
)
}
}
// 在启动时加载属性
startKoin {
androidContext(this@MyApp)
modules(configModule)
fileProperties("/config.properties") // 从assets加载
}
五、测试方案
1. 测试模块配置
kotlin
val testModule = module {
// 覆盖正式实现
single<ApiService>(override = true) { MockApiService() }
single<Database>(override = true) { InMemoryDatabase() }
}
@Before
fun setup() {
startKoin {
modules(testModule)
}
}
@After
fun tearDown() {
stopKoin()
}
2. ViewModel 测试
kotlin
class MainViewModelTest {
private lateinit var viewModel: MainViewModel
@Before
fun setup() {
val testModule = module {
viewModel { MainViewModel(get()) }
single<UserRepository> { FakeUserRepository() }
}
startKoin { modules(testModule) }
viewModel = get()
}
@Test
fun testLoadData() = runTest {
viewModel.loadData()
assertEquals(3, viewModel.users.value?.size)
}
}
六、最佳实践
-
模块化组织:
- 按功能拆分模块(network/database/repository等)
- 每个模块文件不超过200行
-
依赖顺序:
kotlinstartKoin { modules( coreModule, // 基础组件 networkModule, // 网络层 databaseModule, // 数据层 viewModelModule // 最后加载ViewModel ) }
-
生命周期管理:
- 单例用于全局服务
- factory用于无状态工具类
- viewModel严格遵循生命周期
-
命名规范:
kotlinsingle(named("AuthApi")) { createAuthApi(get()) } single(named("PublicApi")) { createPublicApi(get()) } // 使用处 class MyViewModel( @Named("AuthApi") private val authApi: ApiService, @Named("PublicApi") private val publicApi: ApiService ) : ViewModel()
七、常见问题解决
问题1:循环依赖
错误示例:
kotlin
class A(val b: B)
class B(val a: A)
解决方案:
- 使用 lazy 延迟初始化
- 重构设计,引入第三方类
问题2:依赖找不到
检查步骤:
-
确认模块已正确加载
-
检查 get() 参数类型是否匹配
-
查看 Koin 日志:
kotlinstartKoin { androidLogger(Level.DEBUG) }
问题3:内存泄漏
预防措施:
kotlin
// Fragment中正确使用
private val viewModel by viewModels<MyViewModel>()
// 避免在Application中持有Activity引用
通过以上配置和实践,你可以构建出清晰、可维护的Android应用依赖注入体系。Koin的appModule让依赖管理变得直观且类型安全,特别适合Kotlin开发的Android项目。