MVVM学习记录

2018-08-16  本文已影响144人  vb12

这几天突击学了一下arc, 自然navigation, MVVM, lifecycle, DataBinding, LiveData, ViewModel这些概念也都得看.

几种开发模式的对比


如何构建Android MVVM 应用框架
这篇算是我觉得写的很清晰的了, 废话少. 但是我对下面这句保留意见
"每个ViewModel都最好需要持了一个Context的引用" --- 其实谷歌官方还是不建议ViewModel持有context的, 如果有什么工具方法必须用到context, 在方法里面自己去找application的context就好了, 现在有了kotlin, 很多之前觉得不好看的代码, 都可以一笔带过.

google官方示例

google官方示例
官方的实例, 查看它的todo-mvvm-databing分支, 在README中有如下的描述:
The ViewModel in the MVVM architecture plays a similar role to the Presenter in the MVP architecture. The two architectures differ in the way that the View communicates with the ViewModel or Presenter respectively:
--ViewModel 在MVVM 中的作用与Presenter 在mvp中的作用类似, 这两种架构的不同之处在于view组件与ViewModel 和Presenter 的通讯方式.

  1. When the app modifies the ViewModel in the MVVM architecture, the View is automatically updated by a library or framework. You can’t update the View directly from the ViewModel, as the ViewModel doesn't have access to the necessary reference.
    --- 当MVVM 中的ViewModel 变化时, View会自动被系统更新, 你不能在ViewModel中手工更新View, 客观上这是做不到的.

  2. You can however update the View from the Presenter in an MVP architecture as it has the necessary reference to the View. When a change is necessary, you can explicitly call the View from the Presenter to update it.
    In this project, you use layout files to bind observable fields in the ViewModel to specific UI elements such as a TextView, or ImageView. The Data Binding Library ensures that the View and ViewModel remain in sync bi-directionally as illustrated by the following diagram.
    ---- 但是在MVP中, 你必须通过Presenter 对View层进行修改. 通过句柄或者回调. 在这个项目中, 你使用布局文件来绑定fields 到UI控件. 比如TextView, ImageView. Data Binding Library会保证view与ViewModel的同步.

image.png

不管是mvp还是mvvm , 谷歌都把m实现成repository, 完全不以m开头.

LifeCycle


关于lifecycle, 学习这几篇

https://developer.android.google.cn/topic/libraries/architecture/lifecycle

https://www.jianshu.com/p/9b3da5fe0ff6

https://www.jianshu.com/p/ee6b81b9777a

基本上也就看懂了, 内容不算多, 就是通过类库提供了一种机制, 可以知道activity

或者fragment的生命周期, 注意, 是在这两个上下文之外可以知道这两者的生命周期.

这带来两个好处:

1. 对于代码来说, 更简洁, 与activity, fragment的耦合少了.

2. 为一些需要在后台处理的操作提供了方便的接口可以得知当前的生命周期变化.

认真记住官方文档中的最佳实践 best practise

LifeCycle best practise

1. 保持 UI controllers (activities and fragments)越简洁越好,不要臃肿 。UI controllers不要去获取数据,而是用ViewModel来执行,并监听lifeData来更新视图。

2. 尝试编写用数据驱动的UI,UI controllers的职责就是数据改变是更新视图,并且把用户的操作通知给ViewModel。

3. 将业务逻辑放入在VIewModel中,VIewModel应该用作UI控制器和其他应用程序之间的连接器。请注意,ViewModel的责任不是获取数据(例如从网络获取数据),ViewModel应该调用相应的组件来获取数据,然后把结果提供给UI controller。

4. 使用数据绑定来维护视图view和UI控制器接口的清洁。使view视图更具有生命性,减少在fragment或者activity编写更新数据的代码。如果使用Java语言来开发,请使用像Butter Knife这样的库来避免使用样板代

5. 如果UI非常复杂,可以考虑创建一个Persenter类来处理UI的修改。也许使用Persenter有点大材小用,但是可以使ui变得更容易测试

6. 不要在ViewModel中引用View或者Activity中的context,如果ViewModel活的比Activity更长,activity可能会引发内存泄露,而不是正常的垃圾回收。

LifeCycle Event 和 State

Lifecycle类中两个主要的枚举: Event 和 State


image.png

LifecycleObserver类是一个接口, 而且是一个空接口:


public interface LifecycleObserver {

}

在实现这个接口的自定义observer类中, 需要通过注解的方式, 来对应具体的事件

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onMyResume() { } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void onMyPause() { }

对于方法名, onMyResume, onMyPause就不重要了, 随意取.

个方法可以观察多个事件,多个方法也可以观察相同事件

如果想深究一下原理, 看看这篇里面的简单说明:https://www.jianshu.com/p/ee6b81b9777a

补充一点, 如果是在普通Activity类中, 如果要实现LifecycleOwner 接口, 那么在提供LifecycleRegistry 对象之外, 还需要手工的在onCreate, onresume, onStart.....各个生命周期方法中去触发事件. 很麻烦, 所以还是尽量使用support包中的SupportActivity子类吧.

LiveData


那么LiveData又是什么呢?

LiveData是一个机制, 一个接口(实际是几个类), 一种方式,

可能还是得附属到ViewModel 上, 来存储数据,

这篇文章:https://www.jianshu.com/p/14af4b8c29e3 中认为LiveData是用来监听数据变化的. 框架提供了一种监听者的模式, 来保证在LiveData数据变化时通知监听者Observer,

image.png

先继续说LiveData, 这个监听跟之前的各种监听器, 或者自己实现一个监听器, 有什么区别呢? 最大的区别就是这里的监听考虑了监听者的生命周期变化, 如果一个Activity已经pause或者destory了, 那么就不会收到这个状态变化的回调, 怎么做到的? 当然前面提到的LifeCycle框架.

关于LiveData, 最好的还是官方的这个指导

https://developer.android.google.cn/topic/libraries/architecture/livedata

其中最后提到了transformations, Transformations.switchMap

遇到的问题

使用mvvm 或者说使用DataBingding时, 经常遇到as误报的编译错误, clean一遍, 然后再编译就成功了.
另外大部分的xml语法错误, 都无法在编译失败的信息里明确提示出来, 这是使用DataBinding的一个比较不好的地方.
---- 升级为最新的版本, 3.3canary6版本, 好一些了.

如果要在fragment中使用空间名称来引用控件, 必须在onViewCreated()方法中, 如果是在onCreateView() 可能会报空指针.

如何向MutableLiveData<MutableList<String>>()中添加数据?

adapter.submitList()之后, 数据没有刷新, 为什么? 做错了什么?
----https://www.jianshu.com/p/91b7c3bcb29f

代码

https://github.com/shaopx/LiteDig -- 首页-> "关注" 这个列表是使用的mvvm方式开发的

上一篇下一篇

猜你喜欢

热点阅读