1.什么是MVVM?
MVVM全称是Model View ViewModel,Model即数据模型,View指的是Activity或者Fragment,和MVP架构中的数据层、界面层意义是一样的。这里新增的ViewModel,是用来代替Presenter,和底层业务逻辑交互,并持有数据,内部通过LiveData去关联界面View和数据Model。
2.为什么不太推荐使用MVP
MVP架构最大的问题是View和Presenter新增接口太多,同时还需要去手动管理View的生命周期。业务简单还好,接口不会很多。一旦业务量复杂的情况下,使用MVP方式就会很痛苦。
但是用MVVM就可以很好解决这些问题。首先ViewModel和View层之间是不需要接口的,View层通过对特定LiveData数据的观察,就可以把逻辑处理好的数据更新到界面上。同时ViewModel对Activity或者Fragment的生命周期是有感知的,可以很好地管理数据的收发。
可以理解为MVVM架构是一个改进版的MVP架构。
3.MVVM可以不使用dataBinding吗?
MVVM并不等同于DataBinding,只不过二者总是混合在一起使用,导致很多人以为DataBinding就是MVVM。DataBinding是一个实现数据和UI绑定的框架,是构建MVVM模式的一个工具。
我们在架构MVVM模式,特别是业务复杂切追求稳定性的企业级软件的时候,个人并不推荐使用DataBinding。因为DataDinding有个最大的问题是,它的调试比较麻烦,一旦出现问题,可能会显得束手无策,不可控。
4.稳健的软件架构模式
通常是View(Activity/Fragment)-> ViewModel -> Repository ->NetWork/DataBase/三方SDK接口
这里的ViewModel是负责持有数据,而Repository则是提供获取数据和数据加工处理。如图:
关联方式如下:
首先定义ViewModel的构造函数:
class HeFengViewModel(private val repository: HefengRepository) : ViewModel() {
......
}
然后重写Viewmodel的工厂方法,通过工厂方法把Repository参数传进去:
class HeFengModelFactory(val repository : HefengRepository) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return HeFengViewModel(repository) as T
}
}
然后再通过ViewModelProviders获取到ViewModel:
object InjectorUtil {
fun getHeFengModelFactory() = HeFengModelFactory(getHeFengRepository())
}
class HefengActivity : AppCompatActivity() {
val viewModel by lazy { ViewModelProviders.of(this, InjectorUtil.getHeFengModelFactory()).get(HeFengViewModel::class.java) }
}
5.模块module化
对于复杂的项目,把相对独立的模块单独module话是很有必要的,符合高内聚低耦合的设计原则。同时,对于单独的模块代码,可以使用git子仓库submodule对代码做物理隔离,这样有一个好处是:当主项目有多个分支的情况下,修复了子仓库模块的代码后,只需要提交一次,那么所有分支都可以感知到这个修改,而不是每个分支单独改一次。
创建子仓库的方法可以参考如下链接:https://blog.youkuaiyun.com/liang_baikai/article/details/128084635
然后在项目settings.gradle中导入子仓库对应的module:
// 配置各公共module组件,配置后需要在app的build.gradle中添加依赖
def custom = [
customModule: include_custom_module("customModule")
]
deps.custom = custom
def include_custom_module(String moduleName) {
include(":common-${moduleName}")
project(":common-${moduleName}").projectDir = new File("module/custom_module/${moduleName}")
return project(":common-${moduleName}")
}
在主项目对应的app module build.gradle中引用此模块module即可:
implementation deps.custom.customModule