---
# System prepended metadata

title: Kotlin Injection

---

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







