# Kotlin Injection [TOC] **Koin** 目前理解:用来集中定义于一处,整理view model, 变数集中於一个地方 官網 https://insert-koin.io/ RayWender大大(較推) https://www.raywenderlich.com/9457-dependency-injection-with-koin //build.gradle implementation 'org.koin:koin-android:2.1.5' implementation 'org.koin:koin-androidx-scope:2.1.5' implementation 'org.koin:koin-androidx-viewmodel:2.1.5' ## Application 啟動,module可以有很多種 ```kotlin= startKoin { androidContext(this@SMBFApplication) modules(listOf(sportModule, repositoryModule)) } ``` ## 定義module ```kotlin= val repositoryModule = module { //GameDetail factory { GameDetailRepo(get()) } //Betting factory { BettingRepo(get()) } //也有這種的 viewModel { GameViewModel() } viewModel { ProgramViewModel(get()) } } ``` ## 需要實作class ```kotlin= //factory class GameDetailRepo(val service: GameDetailService) { fun postGameDetail(gameDetailBo: GameDetailBo) = service.postGameDetail(gameDetailBo) fun postAllGame(allGameBo: GameDetailBo) = service.postAllGame(allGameBo) } //viewmodel class ProgramViewModel(private val matchRepo: MatchRepo) : BaseViewModel(), KoinComponent { } ``` ## 打API的service ```kotlin= interface GameDetailService { @POST("app/member_API/api_doaction.php") fun postGameDetail(@Body gameDetailBo: GameDetailBo): Single<GameDetailResp> @POST("app/member_API/api_doaction.php") fun postAllGame(@Body allGameBo: GameDetailBo): Single<AllGameResp> } ``` ## 資料長的樣子根據會收到的JSON格式(使用moshi) ```kotlin= @JsonClass(generateAdapter = true) data class GameDetailBo( val Method: String, val Request: Request ) ``` ```kotlin= @JsonClass(generateAdapter = true) data class GameDetailResp( val GameData: List<GameData>?, val cmd: Cmd, val respcode: String, val respmsg: String?, val timestamp: String ) ``` ## factory用的時候,在某一個ViewModel內,不需要繁瑣創建,直接by inject() ```kotlin= fun postAllGame(allGameRequest: Request) { val gameDetailRepo: GameDetailRepo by inject() gameDetailRepo.postAllGame( GameDetailBo( "getAllGame", allGameRequest ) ).ioToUi().subscribe({ dto -> }, { t: Throwable? -> onAllGame.value = Resource.error(t?.message, null) } ).addTo(compositeDisposable) } ``` ## 在某個Fragment裡 ```kotlin=0 //連動LiveData private fun initObserver() { gameViewModel.onAccountLogin.observe(viewLifecycleOwner, Observer { when (it.status) { Status.SUCCESS -> { it.data?.let { accountLoginData -> val gToken = accountLoginData.redirectURL.toUri().getQueryParameter("gToken") gToken?.let { Properties.gameUid = gToken getGameInfo() } ?: run { showErrorMsg(getString(R.string.game_token_fail)) } } } Status.ERROR -> { val errorMsg = it.message ?: getString(R.string.game_token_fail) showErrorMsg(errorMsg) } } }) } //呼叫factory private fun getGameInfo() { gameDetailInfo?.let { gameDetailInfo -> val calendar = MatchUtils.getCalendar() val iPAddress = Utils.getIPAddress(true) val allGameRequest = AllGameRequest( gameDetailInfo.gameDate, gameDetailInfo.ballType.name, "", Langx.ZH_CN.value, iPAddress, gameDetailInfo.competitionType.type, calendar.timeInMillis.toString(), Properties.gameUid ) viewModel.postAllGame(allGameRequest) } ?: run { showErrorMsg() } } ``` ## viewModel用的時候 ```kotlin= private val viewModel by viewModel<LoginViewModel>() val phoneArea = phoneLayout.phoneAreaLabel.text.toString().replace("+", "") val phone = phoneLayout.phoneNumberEt.getPhoneNumber(phoneArea) viewModel.getOtp(phoneArea, phone) ``` **Anko** 目前理解:写code方式编辑UI,代替layout xml Good Extension RxJavaExt.kt ![](https://i.imgur.com/zWf4HVq.png) File list ![](https://i.imgur.com/3Fzrf7L.png) List.kt ![](https://i.imgur.com/OlyeUnW.png) 專案檔案結構範例 ![](https://i.imgur.com/C6i61Tp.png)