Android 带有活动和片段的ViewModel粒度
这个问题的中心是Android应用程序的体系结构使用生命周期组件ViewModel时,最好是为每个片段提供一个ViewModel,还是为订阅片段的父活动提供一个ViewModel?Android 带有活动和片段的ViewModel粒度,android,android-architecture-components,android-viewmodel,Android,Android Architecture Components,Android Viewmodel,这个问题的中心是Android应用程序的体系结构使用生命周期组件ViewModel时,最好是为每个片段提供一个ViewModel,还是为订阅片段的父活动提供一个ViewModel? 我似乎不清楚如何在没有耦合的情况下确定主-细节-片段-活动关系的方向。例如,如果每个片段都有自己的ViewModel,则不清楚活动应该如何知道如何在不耦合(接口、直接函数调用)的情况下进行反应。正如我在评论中提到的,没有独特的方法来实现这一点,但理想情况下,特别是针对您的主/细节流问题,让我们分析提供的默认示例: I
我似乎不清楚如何在没有耦合的情况下确定主-细节-片段-活动关系的方向。例如,如果每个片段都有自己的ViewModel,则不清楚活动应该如何知道如何在不耦合(接口、直接函数调用)的情况下进行反应。正如我在评论中提到的,没有独特的方法来实现这一点,但理想情况下,特别是针对您的主/细节流问题,让我们分析提供的默认示例:
ItemDetialActivity
处理片段创建和显示、制作和菜单操作。请注意,与用户数据无关,只有“系统”句柄。一、 例如,尝试将活动职责限制在导航上,以及菜单按钮处理等你无法避免的事情。现在,ItemListActivity
似乎违反了这一原则,因为它需要显示列表(Google示例只会在这些关注点的分离之间产生混淆,IMHO),我将创建一个单独的片段,其中包含RecyclerView
及其适配器
现在谈谈实质。这是一个非常高级的骨架,我希望你能利用它。检查并实施,如果有任何问题,请返回:
public interface BaseView {
LifecycleOwner lifecycleOwner();
/* perform actions that affect a basic screen status, like hide/show progress bars and errors,
animate views, etc. */
}
public class BaseRepo {
// will contain LiveData instances which will postValues()
}
public class FooRepo extends BaseRepo {
/* will contain access to database and networking functions, either by creating instance methods
or enforcing with an interface, it's up to you. */
}
public class BaseModel<P extends BasePresenter> extends ViewModel {
protected final FooRepo fooRepo; // optional, can be on concretes
<T> void subscribe(LiveData<T> liveData, Observer<T> observer) {
liveData.observe(view.lifecycleOwner(), observer);
}
<T> void unsubscribe(LiveData<T> liveData, Observer<T> observer) {
if (liveData != null) {
liveData.removeObserver(observer);
}
}
...
}
public abstract class BasePresenter<M extends BaseModel, V extends BaseView> implements LifecycleObserver {
protected V view;
protected M model;
public void setModel(M model) {
this.model = model;
}
public final void attachView(V view, Lifecycle lifecycle) {
this.view = view;
lifecycle.addObserver(this);
}
public void setPresenter(P presenter) {
this.presenter = presenter;
this.presenter.setModel(this);
}
...
}
public abstract class BaseFragment implements BaseView {
/* generics is highly encouraged here, I've seen examples of both BasePresenter<P>
and BaseView<P> */
protected P presenter;
/* You should bind layers here, or in the concrete class,
either with Dagger, reflection, or some other way */
@Override
public LifecycleOwner lifecycleOwner() {
return this;
}
...
}
公共接口基本视图{
LifecycleOwner LifecycleOwner();
/*执行影响基本屏幕状态的操作,如隐藏/显示进度条和错误,
为视图等设置动画*/
}
公共类BaseRepo{
//将包含LiveData实例,这些实例将postValues()
}
公共类FooRepo扩展了BaseRepo{
/*将包含对数据库和网络功能的访问,或者通过创建实例方法
或者使用接口强制执行,这取决于您*/
}
公共类BaseModel扩展ViewModel{
受保护的最终FooRepo FooRepo;//可选,可以在混凝土上
void订阅(LiveData、LiveData、Observer){
观察(view.lifecycleOwner(),observer);
}
作废取消订阅(LiveData、LiveData、Observer){
if(liveData!=null){
liveData.removeObserver(观察者);
}
}
...
}
公共抽象类BasePresenter实现LifecycleObserver{
保护V型视图;
保护M模型;
公共模型(M模型){
this.model=模型;
}
公共最终作废附件视图(V视图,生命周期){
this.view=视图;
添加观察者(本);
}
公共void setPresenter(P presenter){
this.presenter=演示者;
this.presenter.setModel(this);
}
...
}
公共抽象类BaseFragment实现BaseView{
/*这里非常鼓励使用泛型,我已经看到了BasePresenter和BasePresenter的示例
和BaseView
*/
受保护的P演示者;
/*您应该在此处或混凝土类中绑定层,
使用匕首、反射或其他方式*/
@凌驾
公共生命周期所有者生命周期所有者(){
归还这个;
}
...
}
现在,对于每个具体的屏幕,您应该创建一个从基础派生的演示者、模型和片段,并在那里执行具体操作。我希望它能有所帮助。如果您正确使用MVVM,那么在片段和活动上同时使用viewmodel将是不正确的。理想情况下,您只需要在一个地方使用它。这是重要的信息。但是,ViewModels应该如何包含在活动或片段中,以及它们应该如何接口,目前尚不清楚。它们充当数据(模型)和视图之间的接口,将更改从前者推到后者。然而,没有直接或“唯一”的方法来做到这一点。这取决于你的架构。在我当前的项目中,我们使用MVP,但是M层包括ViewModels,这应该与MVVM一起使用,但是架构师管理它来实现这种分层,并且每个类都有自己的角色,并且高度解耦。同样,这取决于你的需要。如果你对我有点耐心,我可以做一个简短的回答。今天晚些时候我们会冻结代码。之后,如果没有其他人先于我,我将创建一个小示例。如果您不介意的话,请。你的洞察力已经得到了赞赏。我知道事情是如何分开的,但是片段-活动关系似乎增加了一层不必要的混乱。例如,知道何时关闭细节片段,或传递片段的recyclerview查看加载列表所需的ViewModel。