美文网首页Android进阶
Dagger2在kotlin (模拟实际MVP开发)

Dagger2在kotlin (模拟实际MVP开发)

作者: 吃掉你了喔 | 来源:发表于2017-10-10 18:05 被阅读0次

    @(Alu)

    1.导入Dagger2依赖

    APPbuild.gradle文件中:

    apply plugin: 'kotlin-kapt"
    kapt {
    generateStubs = true
    }
    dependencies {
    ...
    ...
    compile "com.google.dagger:dagger:2.11"
    kapt 'com.google.dagger:dagger-compiler:2.11'
    }
    

    注:必须使用 kapt方式添加注解,否则会出现无法编译自动生成类文件的bug。

    2.需要用的的Daager2基础

    我所理解的dagger2 就是可以让你不需要手动实例化就可以拿到参与注解的类的实例化对象
    表现在MVP里:

    View层不需要实例化就可以随时拿到Presenter的实例化对象,presenter同样可以拿到ViewModel
    因而让MVP开发模式解耦的同时又进一步解耦,且减少代码量。
    这也是我看来需要学习掌握dagger2的必要性。

    在实际开发中dagger2有两种注解模式,也就是依赖注入模式。

    1.在目标依赖类构造函数上使用 @Inject
    **
     * 方式1
     * 在目标依赖类构造函数@Inject 
     *
     */
    
    class A @Inject constructor(private val aa: Aa, private val aaa: Aaa) {
        fun getData() = aa.getData() + aaa.getData()
    }
    
    class Aa @Inject constructor() {
        init {
            println("Aa类初始化后,")
        }
        fun getData() = "在kotlin中使用注解构造方法的方式拿到值"
    }
    
    class Aaa @Inject constructor(private val aa: Aa) {
        init {
            println("Aaa类初始化后,")
        }
    
        fun getData() = "在Aaa中获取到Aa的数据:" + aa.getData()
    }
    
    class B {
        @Inject lateinit var a: A
    
        init {
            DaggerABComponent.create().Inject(this)
        }
    
    fun getData() = a.getData()
    }
    
    @Component
     interface ABComponent {
        fun Inject(b: B)
    }
    

    在代码中我使用@Inject 注解了AAaAaa三个类的构造函数 .
    B 类中,我们拿到 A类的对象,在 A类中 拿到了 Aa,Aaa类的对象 .

    写出 main函数运行测试:

    fun main(args: Array<String>) {
        println(B().getData())
    }
    

    运行main函数得到结果:

    在目标依赖类构造函数@Inject.png
    2.使用 @Module
    /**
     * 方式2 使用@Module
     */
    class C {
        fun getData() = "kotlin中使用@Moudle的方式,获取到了C 的实例化对象"
    }
    
    @Module
    class D {
        @Provides
        fun provideC() = C()
    }
    
    @Singleton
    @Component(modules = arrayOf(D::class))
    interface CDComponent {
        fun inject(e: App)
    }
    
    class App {
        @Inject lateinit var c: C
        init {
            DaggerCDComponent.create().inject(this)
        }
        fun getData() = c.getData()
    }
    

    写出 main函数运行测试:

    fun main(args: Array<String>) {
    println(B().getData())
    println(C().getData())
    }
    

    运行main函数得到结果:

    使用@Module.png

    准备工作已经做好 ,进入正题:

    3.模拟实际MVP模式下的开发

    为什么说模拟,因为是使用普通的java类来代替实际开发的类,原因是这样做有几个好处:
    一是代码量会很小,便于逻辑的体现
    二是所有类都写在一个.kt 文件里,对比参照起来会很舒服.便于理解

    虽说是模拟,但五脏俱全,贴上代码:

    /**
     * 模拟MVP
    */
    
    /**
     * Application
     */
    class App {
        @Inject lateinit var cdComponent: CDComponent
    
        companion object {
            lateinit var instance: App
        }
    
        init {
            instance = this
            DaggerCDComponent.builder().d(D()).build().inject(this)
        }
    }
    
    @Module
    class D {
        @Provides
        fun provideC() = "做一些初始化操作,例如 Retrofit 初始化"
    }
    
    @Singleton
    @Component(modules = arrayOf(D::class))
    interface CDComponent {
        fun inject(e: App)
        fun plus(cdfModule: CDFModule): CDFComponent
    }
    
    @Subcomponent(modules = arrayOf(CDFModule::class))
    interface CDFComponent {
        fun inject(f: F)
    }
    
    @Module
    class CDFModule(private val mView: I) {
        @Provides fun providesView() = mView
    }
    
    
    /**
     * View
     */
    class F : I {
        override fun setData(str: String) {
            println(str)
        }
    
        @Inject lateinit var m: Presenter
    
        init {
            App.Companion.instance.cdComponent.plus(CDFModule(this)).inject(this)
        }
    
        /**
         *  拉取数据
         */
        fun getData() = m.getData()
    }
    
    interface I {
        fun setData(str: String)
    }
    
    /**
     * presenter
     */
    class Presenter
    @Inject constructor(private val mView: I, private val mModel: Model) {
    
        fun getData() {
            /**
             * 网络延迟
             */
            Thread.sleep(2000)
            mView.setData(mModel.getData())
        }
    }
    
    /**
     * Model
     */
    class Model @Inject constructor() {
        fun getData() = "这是数据源"
    }
    

    Application做总初始化,在具体的Activityfragment里 注解拿到 presenter 调取服务请求
    使用I接口回传 数据.

    写出 main函数运行测试:

    fun main(args: Array<String>) {
        App()
        F().getData()
    }
    

    运行main函数得到结果:

    MVP.png

    数据源在两秒延迟后被回传到View层,View层得到结果并打印.

    写的比较仓促,如有问题,望指正。

    相关文章

      网友评论

        本文标题:Dagger2在kotlin (模拟实际MVP开发)

        本文链接:https://www.haomeiwen.com/subject/vcavyxtx.html