具有活动和片段的ViewModel粒度

时间:2018-06-13 17:38:57

标签: android android-architecture-components android-viewmodel

此问题以Android应用程序的体系结构为中心。 使用LifeCycle组件ViewModel时,最好是每个片段有一个ViewModel,还是要为Fragments订阅的父活动创建一个ViewModel?

我似乎不清楚如何在没有某种耦合的情况下定位类似Master-Detail片段 - 活动关系的东西。例如,如果每个Fragment都拥有它自己的ViewModel,那么不清楚Activity如何在没有耦合的情况下知道如何做出反应(接口,直接函数调用)。

1 个答案:

答案 0 :(得分:0)

正如我在评论中所提到的,没有独特的方法来实现这一目标,但理想情况下,非常具体地说明您的主/细节流程问题,让我们分析默认提供的示例:

ItemDetialActivity处理片段创建和显示,FAB和菜单操作。请注意,与用户数据无关,只有" system"处理。例如,我试图限制活动对导航的责任,以及你真的不能避免菜单按钮处理的东西。现在,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;
    }
    ...
}

现在,对于每个具体的屏幕,您应该创建一个从基础派生的演示者,模型和片段,并在那里执行细节。我希望它有所帮助。