Android 带有活动和片段的ViewModel粒度

Android 带有活动和片段的ViewModel粒度,android,android-architecture-components,android-viewmodel,Android,Android Architecture Components,Android Viewmodel,这个问题的中心是Android应用程序的体系结构使用生命周期组件ViewModel时,最好是为每个片段提供一个ViewModel,还是为订阅片段的父活动提供一个ViewModel? 我似乎不清楚如何在没有耦合的情况下确定主-细节-片段-活动关系的方向。例如,如果每个片段都有自己的ViewModel,则不清楚活动应该如何知道如何在不耦合(接口、直接函数调用)的情况下进行反应。正如我在评论中提到的,没有独特的方法来实现这一点,但理想情况下,特别是针对您的主/细节流问题,让我们分析提供的默认示例: I

这个问题的中心是Android应用程序的体系结构使用生命周期组件ViewModel时,最好是为每个片段提供一个ViewModel,还是为订阅片段的父活动提供一个ViewModel?


我似乎不清楚如何在没有耦合的情况下确定主-细节-片段-活动关系的方向。例如,如果每个片段都有自己的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。