1、MVVM模式各部分的定义
1.1、MVVM模式分为3个部分:Model、View和ViewModel。
(1)Model :数据层,包含数据实体和对数据实体的操作。
(2)View : 界面层,对应于Activity、XML、View,负责数据显示以及用户交互。
(3)ViewModel : 关联层,将Model和View进行绑定,Model或View更改时,实时刷新对方。
1.2、注意点
(1)View只做和UI相关的工作,不涉及任何业务逻辑、不涉操作数据、不处理数据。UI和数据严格的分开。
(2)ViewModel只做和业务逻辑相关的工作,不涉任何和UI相关的操作、不持有控件引用,不更新UI。
2、MVVM模式图
3、MVVM的优势和劣势
3.1、MVVM的优势
(1)、使得M,V,VM的解耦更加彻底,在mvp模式中,p需要持有v的引用,才能去刷新ui;在mvvm模式中,View和Model使用databingding进行双向绑定,一方改变会直接通知另外一方,使得viewmodel能专注于业务逻辑的处理,而不需要去关心ui刷新。(最大优势,下面两个可忽略。)
(2)、不需要findViewById也不需要butterknife,不需要拿到具体的View去设置数据等,这些都可以用DataBinding完成。
(3)、不会像MVC一样导致Activity中代码量巨大,也不会像MVP一样出现大量的View接口(Presente与View是通过接口进行交互的)。项目结构更加低耦合。
3.2、MVVM的劣势
MVVM的缺点数据绑定使得Bug很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。
4、Databinding框架
4.1、Databinding和MVVM的关系
MVVM是一种架构模式,DataBinding是一个实现数据和UI绑定的框架,是实现MVVM模式的工具。
4.2、Databinding常用方法
4.2.1、BindingAdapter注解设置自定义属性
public class ImageHelper {
/**
* 1.加载图片,无需手动调用此方法
* 2.使用@BindingAdapter注解设置自定义属性的名称,imageUrl就是属性的名称,
* 当ImageView中使用imageUrl属性时,会自动调用loadImage方法,
*
* @param imageView ImageView
* @param url 图片地址
*/
@BindingAdapter({"imageUrl", "placeHolder",“error"})
public static void loadImage(ImageView view, String url, Drawable holderDrawable, Drawable errorDrawable) {
Glide.with(imageView.getContext())
.load(url)
.placeholder(holderDrawable)
.error(errorDrawable)
.into(imageView);
}
}
使用@BindingAdapter注解设置自定义属性的名称,如上所示,imageUrl就是属性的名称,当ImageView中使用imageUrl属性时,会自动调用loadImage方法,参数imageView为当前使用imageUrl属性的ImageView,参数url为图片地址。
xml中使用自定义属性
Activity中设置图片的url
public class BasicActivity extends AppCompatActivity {
//用户头像
private static final String URL_USER_PIC = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=4138850978,2612460506&fm=200&gp=0.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityBasicBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_basic);
UserBean userBean = new UserBean(URL_USER_PIC, "张三", 24);
binding.setUser(userBean);
}
}
4.2.1、DataBinding动态更新数据的2种方式
(1)、BaseObservable
这个类也实现了字段变动的通知,在变量的getter上使用 Bindable注解,并通过notifyPropertyChanged通知更新即可。
public class DoubleBindBean extends BaseObservable {
// 用 @Bindable 标记过 getxxx() 方法会在 BR 中生成一个 entry。 当数据发生变化时需要调用 notifyPropertyChanged(BR.content) 通知系统 BR.content这个 entry 的数据已经发生变化以更新UI。
private String content; //内容
public DoubleBindBean(String content) {
this.content = content;
}
@Bindable
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
notifyPropertyChanged(BR.content); //通知系统数据源发生变化,刷新UI界面
}
}
(2)、ObservableFields
如果想要省时,或者数据类的字段很少的话,可以使用 ObservableField 以及它的派生 ObservableBoolean、 ObservableByte ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble、 ObservableParcelable 等。
public class DoubleBindBean2 {
//变量需要为public
public final ObservableField username = new ObservableField<>();
}
Observable Collections
除了支持ObservableField,ObservableBoolean,ObservableInt等基础变量类型以外,当然也支持集合框架拉,比如:ObservableArrayMap,ObservableArrayList。使用和普通的Map、List基本相同