本篇给出数据绑定及MVVM框架的总结,主要内容来自《Android编程权威指南》。
MVVM:Model-View-ViewModel,将其中的View的状态和行为抽象化,将视图UI和业务逻辑分开。MVVM架构很好地把控制器里的臃肿代码抽到布局文件里,让开发人员很容易看出哪些是动态界面。同时,它抽出部门动态控制器代码放入ViewModel类,方便开发测试和验证。
DataBinding:一个帮助开发者处理视图与数据交互的工具,即数据绑定。
gradle——Android添加
dataBinding { enabled = true }
把一般布局改造为数据绑定布局
<layout>标签告诉数据绑定工具处理此类,数据绑定工具会自动生成一个绑定类,默认以布局文件命名,如fragment_beat_box.xml绑定类为FragmentBeatBoxBinding。实例化视图层级结构时,实例化FragmentBeatBoxBinding,其getRoot()引着布局视图结构,该类也会引着布局文件里以android:id标签引用的其他视图。
public class BeatBoxFragment extends Fragment { private BeatBox mBeatBox; public static BeatBoxFragment newInstance() { return new BeatBoxFragment(); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBeatBox = new BeatBox(getActivity()); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { FragmentBeatBoxBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_beat_box, container, false); binding.recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),3)); binding.recyclerView.setAdapter(new SoundAdapter(mBeatBox.getSounds())); return binding.getRoot(); } private class SoundHolder extends RecyclerView.ViewHolder { private ListItemSoundBinding mBinding; private SoundHolder(ListItemSoundBinding binding) { super(binding.getRoot()); mBinding = binding; mBinding.setViewModel(new SoundViewModel(mBeatBox)); } public void bind(Sound soud) { mBinding.getViewModel().setSound(soud); mBinding.executePendingBindings(); } } private class SoundAdapter extends RecyclerView.Adapter{ private List mSounds; public SoundAdapter(List sounds) { mSounds = sounds; } @Override public SoundHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(getActivity()); ListItemSoundBinding binding = DataBindingUtil.inflate(inflater, R.layout.list_item_sound, parent, false); return new SoundHolder(binding); } @Override public void onBindViewHolder(SoundHolder holder, int position) { Sound sound = mSounds.get(position); holder.bind(sound); } @Override public int getItemCount() { return mSounds.size(); } }}
视图模型
public class SoundViewModel extends BaseObservable { private Sound mSound; private BeatBox mBeatBox; public SoundViewModel(BeatBox beatBox) { mBeatBox = beatBox; } @Bindable public String getTitle() { return mSound.getName(); } public Sound getSound() { return mSound; } public void setSound(Sound sound) { mSound = sound; notifyChange(); }}
notifyChange()通知绑定类,视图模型对象上所有可绑定属性都已经更新,绑定类会再次运行绑定表达式更新视图数据。setSound(sound)方法一被调用,ListItemSoundBinding就立即知道,并调用list_item_sound.xml布局里指定的Button.setText(String)方法。viewModel.title就是viewModel.getTitle()简写形式。
完整项目