android

ViewModel——Google组件开发

2017-06-09  本文已影响1136人  samychen

  ViewModel类旨在存储和管理与UI相关的数据,以便数据在诸如屏幕旋转之类的配置更改中生存下来。它还处理Activity/Fragment与应用程序的其余部分的通信(例如调用业务逻辑类)。

  之所以要持久化是基于两个原因:如果OS销毁app释放资源,用户数据不会丢失;当网络很差或者断网的时候app可以继续工作。Model是负责app数据处理的组件。它们不依赖于View或者app 组件(Activity,Fragment等),因此它们不会受那些组件的生命周期的影响。保持UI代码的简单,业务逻辑分离可以让它更易管理。

ViewModel的目的是获取并保存Activity或Fragment所必需的信息。Activity或Fragment应该能够观察到ViewModel中的变化

将视图数据所有权与UI控制器逻辑分离是更容易和更有效的。生命周期提供了一个名为ViewModel的新类,一个用于UI控制器的帮助器类,它负责准备UI的数据。在配置更改期间,ViewModel将自动保留,以便其保存的数据立即可用于下一个Activity或Fragment

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<Users>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // do async operation to fetch users
    }
}

现在活动可以访问这个列表如下:

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
        });
    }
}

如果Activity重新创建,它将收到由上一个Activity创建的相同的MyViewModel实例。当所有者Activity销毁时,框架调用ViewModel的onCleared()方法,以便它可以清理资源。

由于ViewModel超出了具体的Activity和Fragment实例,所以它不应该引用View或任何可能持有对活动上下文的引用的类。如果ViewModel需要应用程序上下文(例如,找到系统服务),则可以继承AndroidViewModel类,并在构造函数中接收应用程序的构造函数,子类必须具有接受Application作为唯一参数的构造函数。(因为Application类继承了Context)。

在Fragments之间共享数据

Activity中的两个或多个Fragment需要相互通信。因此这两个Fragment需要定义一些接口描述,并且Activity必须将两者绑定在一起。此外,两个Fragment都必须处理其他Fragment尚未创建或不可见的情况。

通过使用ViewModel对象可以解决这个问题。想象一下主从Fragment的常见情况,其中我们有一个Fragment,用户从列表中选择一个项目,另一个Fragment显示所选项目的内容。

这些Fragment可以使用其Activity范围共享一个ViewModel来处理此通信。

每个片段可以通过其Activity使用相同的键获取ViewModel。

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> 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
        });
    }
}

注意,在获取ViewModelProvider时,两个Fragment都使用getActivity()。这意味着他们都将收到相同的SharedViewModel实例,该实例是Activity的作用域。

这种做法的好处:

ViewModel的生命周期

ViewModel对象在获取ViewModel时被限定为传递给ViewModelProvider的生命周期。ViewModel保留在内存中,直到Activity销毁或Fragment分离之前。


上一篇下一篇

猜你喜欢

热点阅读