東川印記

一本東川,笑看爭龍斗虎;寰茫兦者,度橫佰昧人生。

新的DI工具Koin,替代 dagger2的简单sample

2020年8月21日星期五



赶在吃饭前,无所事事水字数。。。。
1,库引入
koin_version = '2.1.6'
// Koin for Kotlin
implementation "org.koin:koin-core:$koin_version"
// Koin AndroidX ViewModel features
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
// Koin for Android
implementation "org.koin:koin-android:$koin_version"


2,之前用法ViewModel
1)IHelloRepository,这个用来代替数据源的接口
interface IHelloRepository {
    fun hello(): String
}

class HelloRepositoryImpl() : IHelloRepository {

    override fun hello() = "Hello Koin"

}


2)定义一个ViewModel用来对接数据
class HelloViewModel(val repository: IHelloRepository) : ViewModel() {

    fun sayHello() = "${repository.hello()} from $this"

}


3)工厂模式产出ViewModel
class HelloFactory(private var infoRepository: HelloRepository) : ViewModelProvider.Factory {


    //需要修改
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(HelloViewModel::class.java)) {
            return UserViewModel(infoRepository) as T
        }

        throw IllegalArgumentException("UnKnow ViewModel class")
    }
}


4)使用ViewModel展示数据
a)定义

private lateinit var viewModel: HelloViewModel
private lateinit var factory: HelloFactory
private lateinit var repository: HelloRepository
b)初始化
repository = HelloRepository()
factory = HelloFactory(repository)
viewModel = ViewModelProviders.of(this, factory).get(HelloViewModel::class.java)
c)调用
viewModel.sayHello().observe(this, Observer {
    tv_show.text = "is ${it} "
})


3,通过注入代替生成ViewModel
这个真的简单多了呢
1)定义关联
val vmModule = module {

    // single instance of HelloRepository
    single<IHelloRepository> { HelloRepositoryImpl() }

    //vm
    viewModel { HelloViewModel(get()) }
}


2)直接调用

class TestKoinViewModelActivity : FragmentActivity() {

    companion object {
        fun starter(ctx: Context) {
            var intent = Intent(ctx, TestKoinViewModelActivity::class.java)
            ctx.startActivity(intent)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        KoinContextHandler.stop() //之前的如果初始化了就先stop(),不然会崩
        // Start Koin,放到application,初始化一次即可
        //Now that we have a module, let’s start it with Koin. Open your application class, or make one (don’t forget to declare it in your manifest.xml). Just call the startKoin() function:
        startKoin {
            androidLogger()
            androidContext(applicationContext)
            modules(vmModule)
        }

        //便可以获取到viewModel了
        //The MyViewModel component will be created with HelloRepository instance. To get it into our Activity, let’s inject it with the by viewModel() delegate injector:

        //Lazy Inject ViewModel
        //The by viewModel() function allows us to retrieve a ViewModel instance from Koin, linked to the Android ViewModelFactory.
        val viewModel: HelloViewModel by viewModel() //可以定义为类变量

        setContentView(R.layout.vm_activity_test_koin)

        btn_test_koin.setOnClickListener { btn_test_koin.text = viewModel.sayHello() }

        //这个可以独立使用,不用 by viewModel()
        //The getViewModel() function is here to retrieve directly an instance (non lazy)
        btn_test_koin_get.setOnClickListener {
            btn_test_koin_get.text = getViewModel<HelloViewModel>().sayHello()
        }


    }

}


4,之前用法Presenter
当然是直接new
1)定义

private IMemberListPresenter presenter;
2)初始化

presenter = new MemberListPresenterImpl(); presenter.attachView(activity, this);
3)使用
presenter.refreshData();


5,使用dagger2注入生成Presenter
感觉这个更强大,但是出了异常不好找,不利于团队协作,容易打架。。。。

1)定义

@Inject IUserBlackListPresenter presenter;
2)初始化
DaggerIPresenterComponent.builder().build().inject(this); presenter.attachView(activity, this); presenter.init();


3)使用
presenter.refreshData();


6,通过Koin注入代替生成Presenter

这个就很简单了,而且报错堆栈也很清晰。。。。就是kotlin语言太naive,不方便看源码。。。。

1)定义Presenter
interface IHelloPresenter {
    fun hello(): String
}

class HelloPresenterImpl(val repo: IHelloRepository) : IHelloPresenter {

    override fun hello() = "${repo.hello()} from $this"

}


2)关联Module
val presenterModule = module {

    // single instance of HelloRepository
    single<IHelloRepository> { HelloRepositoryImpl() }

    // Simple Presenter Factory
    //factory { HelloPresenterImpl(get()) } //// Will match type HelloPresenterImpl only
//    factory { HelloPresenterImpl(get()) as IHelloPresenter }    // Will match type IHelloPresenter only
    factory<IHelloPresenter> { HelloPresenterImpl(get()) }    // Will match type IHelloPresenter only

}


3)直接调用
class TestKoinPresenterActivity : FragmentActivity() {


    companion object {
        fun starter(ctx: Context) {
            var intent = Intent(ctx, TestKoinPresenterActivity::class.java)
            ctx.startActivity(intent)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        KoinContextHandler.stop() //之前的如果初始化了就先stop(),不然会崩
        // Start Koin
        startKoin {
            androidLogger()
            androidContext(applicationContext)
            modules(presenterModule)
        }

        //The by inject() function allows us to retrieve Koin instances, in Android components runtime (Activity, fragment, Service…)
        val presenter: IHelloPresenter by inject() //延迟注入
//        val presenter = get<HelloPresenterImpl>()    //无延迟,同按钮2

        setContentView(R.layout.vm_activity_test_koin)

        btn_test_koin.setOnClickListener {
            btn_test_koin.text = presenter.hello()
        }

        //The get() function is here to retrieve directly an instance (non lazy)
        btn_test_koin_get.setOnClickListener {
            btn_test_koin_get.text = get<IHelloPresenter>().hello()
        }


    }


}


简单了许多。。。。
顺便看了下GitHub上的issue,只有
只有 129个Open呢。。。。。。。。

2020年08月21日13:17:33


 大家知道,衣服越少,武力值越高!
大家知道,衣服越少,武力值越高!

--
senRsl
2020年08月21日11:27:46

没有评论 :

发表评论