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