第二十章 数据绑定与MVVM
MVVM
- 这里的视图分为两部分(都为用户可以看到的界面):布局文件和
Activity
、fragment
。 - MVVM架构很好的把控制器里的代码抽到布局文件中,让人看出那些是动态界面。同时他还抽出部分代码到ViewModel类中,方便测试和验证。
- 由于使用数据绑定,结构关系发生了变化。为了避免破坏单一性原则,将
MVC
-> MVVM
。
数据绑定
- 启用数据绑定(在build.gradle文件中)
android {
..........
dataBinding{
enabled = true
}
}
- 数据绑定的布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<variable
name = "viewModel"
type = "com.bignerdranch.andriod.beatbox.SoundViewModel"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:onClick="@{() -> viewModel.onButtonClicked()}"
android:text="@{viewModel.title}"
tools:text="Sound name" />
</FrameLayout>
</layout>
- 由于
<layout>
标签,数据绑定工具会自动生成绑定类,类名默认以布局文件名命名 - 实例化布局
...Binding binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_beat_box, container, false);
binding.getRoot()
引用着整个视图- 使用数据绑定类更新
ViewModel
, ViewModel
更新了, 但视图没有更新.会造成RecyclerView的刷新有问题. - 视图模型不会给布局反馈信息, 所以让视图模型实现数据绑定的接口(
Observable
), 这个接口可以让数据绑定在视图模型上设置监听, 当视图模型发生变化,绑定类立刻会接到回调. - 简单做法是实现
BaseObservable
:
1.在视图模型中继承BaseObservable
类
2.使用@bindable 注解视图模型可绑定的属性
3.使用notifyChange();
//通知绑定类,可绑定属性已经更新。据此绑定类会调用布局中的表达式更新视图。
4.当更新速度过快时(比如在RecyclerView
中), 可使用Binding.executePendingBindings();
迫使视图强制刷新.
@Bindable
public String getTitle(){
return mSound.getName();
}
public void setSound(Sound sound) {
mSound = sound;
notifyChange();
}
private class SoundHolder extends RecyclerView.ViewHolder{
private ListItemSoundBinding mBinding;
public SoundHolder(@NonNull ListItemSoundBinding binding) {
super(binding.getRoot());
mBinding = binding;
mBinding.setViewModel(new SoundViewModel(mBeatBox));
}
public void bind(Sound sound){
mBinding.getViewModel().setSound(sound);
mBinding.executePendingBindings();
}
}
导入assets
- 无需配置管理, 可以随意命名assets. 同时也可以按照自己的文件结构组织他们.
- 无法在布局或其他资源中自定使用他们.
- assets 可以看做随应用打包的微型文件系统, 支持任意层次的文件目录结构, 通常用来加载大量图片与声音资源. Android资源系统不予许把这些文件放在一个目录下管理, 如果使用资源系统一个个处理, 效率会非常慢.
- 使用assets
1.获取AssetManager
AssetManager mAssets = context.getAssets();
2.列出文件名
private static final String SOUND_FOLDER = "sample_sound";
soundNames = mAssets.list(SOUND_FOLDER);
相关小记
- 实践中的任何场景下, 所有context的AssetManager都管理着同一套assets资源.
- 有时会给某些特别属性赋予一些定制行为. 一般行为是写一个bindingAdapter(P334)