Android Kotlin 依賴注入全解:Koin appModule 配置與多 ViewModel 數據共享實戰指南

一、基礎配置與概念

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

六、最佳實踐

  1. 模塊化組織

    • 按功能拆分模塊(network/database/repository等)
    • 每個模塊文件不超過200行
  2. 依賴順序

    startKoin {modules(coreModule,      // 基礎組件networkModule,   // 網絡層databaseModule,  // 數據層viewModelModule  // 最后加載ViewModel)
    }
    
  3. 生命周期管理

    • 單例用于全局服務
    • factory用于無狀態工具類
    • viewModel嚴格遵循生命周期
  4. 命名規范

    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:依賴找不到

檢查步驟

  1. 確認模塊已正確加載
  2. 檢查 get() 參數類型是否匹配
  3. 查看 Koin 日志:
    startKoin {androidLogger(Level.DEBUG)
    }
    

問題3:內存泄漏

預防措施

// Fragment中正確使用
private val viewModel by viewModels<MyViewModel>()// 避免在Application中持有Activity引用

通過以上配置和實踐,你可以構建出清晰、可維護的Android應用依賴注入體系。Koin的appModule讓依賴管理變得直觀且類型安全,特別適合Kotlin開發的Android項目。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81167.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81167.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81167.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

學習記錄:DAY21

我的開發日志&#xff1a;類路徑掃描、DI 容器與動態代理 前言 我失憶了&#xff0c;完全不記得自己早上干了什么。 日程 早上 10 點左右開始&#xff0c;學了一早上&#xff0c;主要是類路徑掃描相關的調試。 晚上 8 點了&#xff0c;真不能再摸&#x1f41f;了。 學習記錄 計…

【Agent】MCP協議 | 用高德MCP Server制作旅游攻略

note MCP (Model Context Protocol) 代表了 AI 與外部工具和數據交互的標準建立。MCP 的本質&#xff1a;它是一個統一的協議標準&#xff0c;使 AI 模型能夠以一致的方式連接各種數據源和工具&#xff0c;類似于 AI 世界的"USB-C"接口。 它能夠在 LLM/AI Agent 與外…

使用 Spring Data Redis 實現 Redis 數據存儲詳解

使用 Spring Data Redis 實現 Redis 數據存儲詳解 Spring Data Redis 是 Spring 生態中操作 Redis 的核心模塊&#xff0c;它封裝了 Redis 客戶端的底層細節&#xff08;如 Jedis 或 Lettuce&#xff09;&#xff0c;提供了統一的 API 來操作 Redis 的數據結構。以下是詳細實現…

Qt5與現代OpenGL學習(四)X軸方向旋轉60度

把上面兩張圖像放到D盤1文件夾內&#xff1a; shader.h #ifndef SHADER_H #define SHADER_H#include <QDebug> #include <QOpenGLShader> #include <QOpenGLShaderProgram> #include <QString>class Shader { public:Shader(const QString& verte…

【Machine Learning Q and AI 讀書筆記】- 02 自監督學習

Machine Learning Q and AI 中文譯名 大模型技術30講&#xff0c;主要總結了大模型相關的技術要點&#xff0c;結合學術和工程化&#xff0c;對LLM從業者來說&#xff0c;是一份非常好的學習實踐技術地圖. 本文是Machine Learning Q and AI 讀書筆記的第2篇&#xff0c;對應原…

using var connection = connectionFactory.CreateConnection(); using var 是什么意思

在 .NET 中&#xff0c;??垃圾回收&#xff08;Garbage Collection, GC&#xff09;?? 確實是自動管理內存的機制&#xff0c;但它 ??僅適用于托管資源&#xff08;Managed Resources&#xff09;??&#xff08;如類實例、數組等&#xff09;。然而&#xff0c;對于 ?…

Multicore-TSNE

文章目錄 TSNE使用scikit-learn庫使用Multicore-TSNE庫安裝方法基本使用方法采用不同的距離度量 其他資料 TSNE t-Distributed Stochastic Neighbor Embedding (t-SNE) 是一種高維數據的降維方法&#xff0c;由Laurens van der Maaten和Geoffrey Hinton于2008年提出&#xff0…

SI5338-EVB Usage Guide(LVPECL、LVDS、HCSL、CMOS、SSTL、HSTL)

目錄 1. 簡介 1.1 EVB 介紹 1.2 Si5338 Block Diagram 2. EVB 詳解 2.1 實物圖 2.2 基本配置 2.2.1 Universal Pin 2.2.2 IIC I/F 2.2.3 Input Clocks 2.2.4 Output Frequencies 2.2.5 Output Driver 2.2.6 Freq and Phase Offset 2.2.7 Spread Spectrum 2.2.8 快…

Spring AI應用系列——基于OpenTelemetry實現大模型調用的可觀測性實踐

一、項目背景與目標 在AI應用日益復雜的今天&#xff0c;大模型服務&#xff08;如語言理解和生成&#xff09;的性能監控和問題排查變得尤為關鍵。為了實現對大模型調用鏈路的可觀測性&#xff08;Observability&#xff09;管理&#xff0c;我們基于 Spring Boot Spring AI…

Spyglass:官方Hands-on Training(一)

相關閱讀 Spyglasshttps://blog.csdn.net/weixin_45791458/category_12828934.html?spm1001.2014.3001.5482 本文是對Spyglass Hands-on Training中第一個實驗的翻譯&#xff08;有刪改&#xff09;&#xff0c;Lab文件可以從以下鏈接獲取。Spyglass Hands-on Traininghttps:…

PCB設計工藝規范(三)走線要求

走線要求 1.走線要求2.固定孔、安裝孔、過孔要求3.基準點要求4.絲印要求 1.走線要求 印制板距板邊距離:V-CUT 邊大于 0.75mm&#xff0c;銑槽邊大于0.3mm。為了保證 PCB 加工時不出現露銅的缺陷&#xff0c;要求所有的走線及銅箔距離板邊:V-CUT邊大于 0.75mm&#xff0c;銑槽邊…

抓取工具Charles配置教程(mac電腦+ios手機)

mac電腦上的配置 1. 下載最新版本的Charles 2. 按照以下截圖進行配置 2.1 端口號配置&#xff1a; 2.2 https配置 3. mac端證書配置 4. IOS手機端網絡配置 4.1 先查看電腦上的配置 4.2 配置手機網絡 連接和電腦同一個wifi&#xff0c;然后按照以下截圖進行配置 5. 手機端證書…

【CSS】精通Flex布局(全)

目錄 1. flex布局體驗 1.1 傳統布局 與 flex布局 1.2 初體驗 2. flex布局原理 2.1 布局原理 3. flex布局父項常見屬性 3.1 常見父項屬性 3.2 屬性值 3.3 justify-content 設置主軸上的子元素排列方式 3.4 flex-wrap設置子元素是否換行 3.5 align-items 設置側軸上的…

力扣第447場周賽

這次終于趕上力扣的周賽了, 賽時成績如下(依舊還是三題 )&#xff1a; 1. 統計被覆蓋的建筑 給你一個正整數 n&#xff0c;表示一個 n x n 的城市&#xff0c;同時給定一個二維數組 buildings&#xff0c;其中 buildings[i] [x, y] 表示位于坐標 [x, y] 的一個 唯一 建筑。 如…

AI中常用概念的理解

1. RAG&#xff08;檢索增強生成&#xff09; 通俗理解&#xff1a;就像你寫作業時&#xff0c;先查課本 / 百度找資料&#xff0c;再根據資料寫答案&#xff0c;而不是純靠記憶瞎編。 AI 模型&#xff08;比如 ChatGPT&#xff09;回答問題時&#xff0c;先去 “數據庫 / 互聯…

SQLServer多版本兼容Java方案和數據采集

Maven引入 <dependency><groupId>com.microsoft.sqlserver</groupId><artifactId>sqljdbc4</artifactId><version>4.0</version></dependency><dependency><groupId>net.sourceforge.jtds</groupId><ar…

【每日八股】復習 Redis Day4:線程模型

文章目錄 復習 Redis Day4&#xff1a;線程模型介紹一下 Redis 的線程模型核心線程模型&#xff08;Redis 6.0 之前&#xff09;Redis 6.0 的多線程改進Redis 真的是單線程嗎&#xff1f;Redis 的線程模型剖析 上一篇 Redis 的應用我今天才完成&#xff0c;因此明天一并復習 Re…

樹莓派智能攝像頭實戰指南:基于TensorFlow Lite的端到端AI部署

引言&#xff1a;嵌入式AI的革新力量 在物聯網與人工智能深度融合的今天&#xff0c;樹莓派這一信用卡大小的計算機正在成為邊緣計算的核心載體。本文將手把手教你打造一款基于TensorFlow Lite的低功耗智能監控設備&#xff0c;通過MobileNetV2模型實現實時物體檢測&#xff0…

vs2019編譯occ7.9.0時,出現fatal error C1060: compiler is out of heap space

問題描述 visual studio 2019編譯opencascade 7.9.0時&#xff0c;出現編譯錯誤 fatal error C1060: compiler is out of heap space 解決方案 修改vs2019并行編譯的線程個數&#xff0c;默認是12個&#xff0c;我改成了4個&#xff0c;問題解決 Tools > Project and Sol…

vue跨域問題總結筆記

目錄 一、Websocket跨域問題 1.nginx配置 2.VUE CLI代理 3.env.development配置 4.nginx日志 5.解決 一、解決跨域的幾種常用方法 1.Vue CLI代理 2.JSONP 3.WebSocket 4.NGINX解決跨域問題 6.Java解決跨域 二、Vue跨域問題詳解 1. 什么是跨域 2. 跨域的例子 3.…