Android Kotlin 依赖注入全解:Koin appModule 配置与多 ViewModel 数据共享实战指南

一、基础配置与概念

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)
    }
}

六、最佳实践

  1. 模块化组织

    • 按功能拆分模块(network/database/repository等)
    • 每个模块文件不超过200行
  2. 依赖顺序

    kotlin 复制代码
    startKoin {
        modules(
            coreModule,      // 基础组件
            networkModule,   // 网络层
            databaseModule,  // 数据层
            viewModelModule  // 最后加载ViewModel
        )
    }
  3. 生命周期管理

    • 单例用于全局服务
    • factory用于无状态工具类
    • viewModel严格遵循生命周期
  4. 命名规范

    kotlin 复制代码
    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:循环依赖

错误示例

kotlin 复制代码
class A(val b: B)
class B(val a: A)

解决方案

  • 使用 lazy 延迟初始化
  • 重构设计,引入第三方类

问题2:依赖找不到

检查步骤

  1. 确认模块已正确加载

  2. 检查 get() 参数类型是否匹配

  3. 查看 Koin 日志:

    kotlin 复制代码
    startKoin {
        androidLogger(Level.DEBUG)
    }

问题3:内存泄漏

预防措施

kotlin 复制代码
// Fragment中正确使用
private val viewModel by viewModels<MyViewModel>()

// 避免在Application中持有Activity引用

通过以上配置和实践,你可以构建出清晰、可维护的Android应用依赖注入体系。Koin的appModule让依赖管理变得直观且类型安全,特别适合Kotlin开发的Android项目。

相关推荐
橙子199110161 小时前
请简述一下什么是 Kotlin?它有哪些特性?
android·开发语言·kotlin
贫道绝缘子2 小时前
【Android】四大组件之Service
android
weixin_472339462 小时前
Android Studio下载安装教程
android·ide·android studio
西楚曹长卿3 小时前
RN 获取视频封面,获取视频第一帧
android·react native·音视频·react
建群新人小猿3 小时前
CRMEB-PRO系统定时任务扩展开发指南
android·java·开发语言·前端
百流4 小时前
ES使用之查询方式
android·大数据·elasticsearch
每次的天空5 小时前
Android学习总结之自定义view设计模式理解
android·学习·设计模式
是店小二呀6 小时前
【优选算法 | 前缀和】前缀和算法:高效解决区间求和问题的关键
android·c++·算法
l and6 小时前
适配 AGP8.5,maven 私服发布报错(七)
android·maven