如上所示,MVVM是Mode-View-ViewMode模式:
Model :负责数据实现和逻辑处理,类似MVP。
View : 对应于Activity和XML,负责View的绘制以及与用户交互,类似MVP。
ViewModel : 创建关联,将model和view绑定起来,如此之后,我们model的更改,通过viewmodel反馈给view,从而自动刷新界面
MVVM优点?
MVVM缺点?
1、首先我们先定义一个简单的ViewMode,这边会把LiveData放到ViewMode里面进行维护,目的是为了更好区分Mode和LiveData的逻辑,如果把LiveData放到Mode里面,当数据出现问题时我们还得排除是LiveData本身数据通知问题还是Mode本身数据处理问题,所以个人还是比较赞同把LiveData放到ViewMode里面,这样比较好维护
public class MyViewModel extends ViewModel {
private MutableLiveData> users;
public LiveData> getUsers() {
if (users == null) {
users = new MutableLiveData>();
loadUsers();
}
return users;
}
private void loadUsers() {
// do async operation to fetch users
}
}
另外上面的loadUsers方法本身就是调用Mode层获取数据,这个数据可以是数据库相关、网络相关、文件相关等,这边就不具体写了
2、定义View层,即Activity和layout,View层会持有ViewMode对象,是单向持有,ViewMode不能包含任何View相关的控件,也不需要关心任何View层逻辑
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
上面就是一个简单的MVVM结构了,是不是感觉Activity一下子简洁了很多,测试时可以更换View复用ViewMode,也可以更换ViewMode复用View,这样设计单元测试用例就简洁多了,不过在设计的时候不要太多关注ViewMode的输入输出,更多关注View层和Mode层的逻辑是否正确
public class SharedViewModel extends ViewModel {
private final MutableLiveData- selected = new MutableLiveData
- ();
public void select(Item item) {
selected.setValue(item);
}
public LiveData
- getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onActivityCreated() {
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends LifecycleFragment {
public void onActivityCreated() {
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// update UI
});
}
}
这边涉及到ViewMode的生命周期了,可以看一下下面的代码:
ViewModelStore的定义
public class ViewModelStore {
private final HashMap mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
}
ViewModelProviders的of方法
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
ViewModelProviders的get方法
public T get(@NonNull String key, @NonNull Class modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
FragmentActivity的onDestroy方法
@Override
protected void onDestroy() {
super.onDestroy();
if (mViewModelStore != null && !isChangingConfigurations()) {
mViewModelStore.clear();
}
mFragments.dispatchDestroy();
}
然后我们来解释一下为什么可以做到fragment间数据共享:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
这边是基于Lifecycle来实现生命周期绑定的,lifecycle方面就不多做介绍了,可以看到对livedata对象进行监听时会在当前Activity对应的lifecycle中加入一个观察者,这样livedata就能获取到activity对应的生命周期通知,然后livedata做了几件事:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}