MVVM模块化架构

  1. 原文 我放在Github上啦,Github上会第一时间更新文章
  2. 这次的MVVM不是传统上的,而是需要配合Google的 ViewModel,LiveData使用的。
  3. 严重使用了 Dagger2,轻度依赖了ARouter。

ViewModel

  1. ViewModel 是要交给 Dagger 来管理的,比如:

    class UserActivityVM @Inject constructor(application: Application): BaseViewModel() {}
    复制代码
  2. ViewModel 不知道它是给哪个 View (MVVM中的V)提供服务的,也就是说它不能持有 Activity 实例,甚至不能有Context出现,当然ApplicationContext除外。

  3. ViewModel的生命周期是要比 Activity/Fragment 长的,所有 ViewModel 中的对 View 的更新都使用 LiveData 让 View 订阅更新。

View

  1. 使用 Dagger2 将需要的 ViewModel Inject进来,因为这个是通用操作,可以写在 BaseActivity/BaseFragment中,例如:

    @Inject
    lateinit var factory: ViewModelProvider.Factory
    
    val viewModel: T by lazy {
        val observer = ViewModelProviders.of(this, factory).get((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>)
        lifecycle.addObserver(observer)
        observer
    }
    复制代码
  2. 在 Activity/Fragment 中订阅 ViewModel 中的 LiveData,以获取需要的数据。比如:

    viewModel.nickName.observe(this, Observer { if (null != it) nickName.text = it })
    复制代码
  3. Activity/Fragment 不能调用 ViewModel中的耗时方法(因为ViewModel的生命周期是比View长的),Activity/Fragment 从 ViewModel 获取的所有数据都只能通过 LiveData 获取,而不能直接调用返回结果。

  4. 番外:在View中使用SimplifyDagger可以少些好几吨 Dagger 代码。

模块化

  1. 一些公用模块,比如 Utils,Resources,Widgets等业务逻辑无关的,可以被其他任何一个模块依赖。
  2. 创建 DaggerModule,用来管理所有业务模块。
  3. 业务模块A,B,C等,互相之间不能有依赖关系,全部被DaggerModule依赖。

模块间通信(api化)

  1. 若模块A想暴露某个功能给其他模块使用,则在_apis_文件夹下写一个 interface,然后在其他地方实现这个 interface,然后交给 dagger:

    @AppScope
    @Binds
    public abstract UserInfo privideUserInfo(UserInfoImpl impl);
    复制代码
  2. _apis_文件夹暴露出去:

    1. gradle脚本

      apply plugin: 'maven-publish'
         
         task sourceJar(type: Jar) {
             from fileTree(dir: "${project.projectDir.absolutePath}/build/intermediates/javac/debug/classes", include: '**/_apis_/**/*.class')
             from fileTree(dir: "${project.projectDir.absolutePath}/build/tmp/kapt3/incrementalData/debug", include: '**/_apis_/**/*.class')
         }
         
         publishing {
             publications {
                 bar(MavenPublication) {
                     groupId 'io.github.hurshi'
                     artifactId project.name
                     version '1.0'
                     artifact(sourceJar)
                 }
             }
             repositories {
                 maven {
                     url "${rootProject.projectDir.absolutePath}/repo"
                 }
             }
         }
      复制代码
    2. shell 脚本

      ../gradlew clean -p ../
      ../gradlew assembleDebug -p ../
      ../gradlew publish -p ../
      复制代码
    3. 在需要使用这个模块的 build.gradle 中添加:

      compileOnly "io.github.hurshi:UserInfo:1.0"
      复制代码
    4. 这样,我们就将_apis_文件夹下的 interface 都暴露出去了,以此完成模块间的通信。

  3. 模块间通信原理:我们写一个 interface,然后把实现这个 interface 的实例Z交给 dagger,当其他模块拿着这个interface 问dagger要实例的时候,dagger 就会把实例Z返回,其实是Dagger在帮你把实例Z从模块A拿到了其他模块。而_apis_相当于把实例Z的"key"拿到了其他模块(interface相当于是实例Z的"key").

转载于:https://juejin.im/post/5bfba0a96fb9a049ab0d49e1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值