Day 20:让我来为您服务.由Koin管理的Android App

Keyword:Koin,Koin Compent
到Day20 使用Koin管理依赖注入显示在Android上 放在这边
KMMDay20


我们先在Android使用昨天建立的Koin物件吧.就跟正常的Koin使用流程一样,需要在Android的App启动时进行Koin的启动,因此我们在Android的根目录建立一个新的物件CafeApplication并且继承Application,让Koin可以在这里启动,有多第三方库也会要求使用时必须在Application预先载入.如果有用到其他部分的组件,请务必在Koin之後再开始启动流程.不然这块的物件就会超脱Koin的管理,这样就失去了依赖注入的特性了.

import android.app.Application
import android.content.Context
import com.officeyuli.kmmforit.initKoin
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

class CafeApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        initKoin(
            module {
                single<Context> { this@CafeApplication }
                viewModel { MainViewModel() }
            }
        )
    }
}

在这里我们呼叫了昨天写好的一个funcion ,initKoin,回去看initKoin有要求提供一个appModule,这边就交由各平台实作.那Android这边有两个特别的物件建立或提供,第一个就是ApplicationContext,不管是使用DB或是SharedPreferences都需要这个,所以先交给Koin帮我们管理(当然在iOS就没有需要这个了),在几天後的DB使用教学就会用到了

另外一个就是ViewModel,在一般的Android App里面,使用ViewModel的时候需要提供生命周期的宿主,像是某一个Activity或是Fragment,但是我们藉由Koin提供的DSL,可以自动根据ViewModel所在的View层物件,来自动建立对应的ViewModel.是不是很方便呢.

这边有一点要特别注意,因为viewModel这个Term太多人使用了,在使用Koin的viewModel功能时,要注意不要使用到错误的import.所以我今天特别把import加了上去.

接下来要让Android系统知道启动的时候要呼叫这个Application,所以修改androidApp内的AndroidManifest.xml.在application的tag内加上指定的Application,也就是刚刚建立的CafeApplication.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.officeyuli.kmmforit.android">

    <application
        android:name=".CafeApplication"//加入这行来指定启动时使用的预设Application
        android:allowBackup="false"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
         ...
					>
        </activity>
    </application>
</manifest>

然後我们修改MainViewModel,让其实作KoinComponent这个interface.这是为了让Koin可以提供,我们不用做特别的动作.

然後根据我们昨天写的Module,现在Koin知道如何提供DataRepositoy的实体了,那麽我们可以使用by inject()方法,让Koin来代替我们完成物件的建立.现在MainViewModel不用知道这些物件怎麽建立的了.

class MainViewModel : ViewModel(), KoinComponent {
    private val dataRepository: DataRepository by inject()
    private val cafeList = MutableLiveData<List<CafeResponseItem>>()
    val cafeListLiveData: LiveData<List<CafeResponseItem>> = Transformations.map(cafeList) { it }

    fun fetchCafeData(city: String = "") {
        viewModelScope.launch() {
            val result = async { dataRepository.fetchCafesFromNetwork(city) }
            cafeList.value = result.await()
        }
    }
}

同样的,Activity内的viewModel宣告,由於Koin已经自动帮我们建立好了ViewModel的建立过程,因此可以由Koin代为效劳.我们把里面的MainViewModel建立过程替换掉.

import org.koin.androidx.viewmodel.ext.android.viewModel
class MainActivity:AppCompatActivity() {
	...
private val viewModel : MainViewModel by viewModel()
	...
}

同样要注意viewModel不要用错了,要import的是koin的.

之前我们的ViewModel是可变数var,而在使用Koin提供後,会要求改变为不可变数val,这样就不会在使用流程中,再次的重新定义给viewModel变数了.这样物件的建立与销毁都由Koin来管理.

执行起来,跟原本的状态是一样的,但是MainActivity ,MainViewModel与DataRepository的耦合程度大大的降低了.

今天完成了Android的部分,我们明天会来做iOS的部分


<<:  [Day10 ] NAT Slipstreaming

>>:  JavaScript入门 Day20_function介绍3

# Day 17 Physical Memory Model (二)

文件 Physical Memory Model 翻译: SPARSEMEM ========= S...

#22 IPAPAPI - IP as Picture API

今天来用 Cloudflare Workers 写个有趣的东西吧! 你的 IP 是不是 ? 很酷吧!...

Chapter4 - Canvas背景动画(IV)把纷飞的落叶,通通抓回来当作收藏吧!

今天挑战半小时写完一篇文章(被打,其实我写完程序了,把文章撰写出来就好噜。 https://jerr...

【Day19】:PWM输出-模拟类比讯号

PWM-脉冲宽度调变 我相信很多人在使用Arduion的时候还是不清楚PWM到底在干嘛? PWM是一...

30天学会C语言: Day 9-Arrrrrrrrrrrrray~~

目前的内容中,一个变数在同一个时间只能储存一个资料,如果有多笔资料就需要有多个变数 如果要计算三个数...