【问题标题】:ViewModel granularity with Activities and Fragments具有活动和片段的 ViewModel 粒度
【发布时间】:2018-06-13 17:38:56
【问题描述】:

此问题围绕 Android 应用程序的架构展开。 在使用 LifeCycle 组件 ViewModel 时,最好是每个 Fragment 有一个 ViewModel 还是为 Fragments 订阅的父 Activity 一个 ViewModel?

我似乎不清楚如何在没有耦合的情况下定位主-细节片段-活动关系之类的东西。例如,如果每个 Fragment 都有自己的 ViewModel,则不清楚 Activity 应该如何知道如何在不耦合的情况下做出反应(接口、直接函数调用)。

【问题讨论】:

  • 我正确使用了 MVVM,在片段和活动上都有视图模型是不正确的。理想情况下,您只需要在一个地方使用它。
  • 这是重要信息。然而,仍然不清楚 ViewModel 应该如何包含在活动或片段中,以及它们应该如何交互。
  • 它们充当数据(模型)和视图之间的接口,将更改从前者推送到后者。但是,没有直接或“唯一”的方法可以做到这一点。这真的取决于你的架构。在我当前的项目中,我们使用 MVP,但 M 层包含 ViewModels,它应该与 MVVM 一起使用,但架构师管理它以很好地实现这种分层,并且每个类都有自己的角色并且高度解耦。同样,这取决于您的需求。
  • 如果你对我有点耐心,我可以做一个简短的回答。今天晚些时候我们有一个代码冻结。之后,我将创建一个小示例,如果没有其他人先于我。
  • 如果您不介意,请。您的洞察力已经受到赞赏。我知道事物是如何分离的,但是片段-活动关系似乎增加了不必要的混乱层。例如,知道何时关闭细节片段或将片段的 recyclerview 传递给它需要加载列表的 ViewModel。

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


【解决方案1】:

正如我在 cmets 中提到的,没有唯一的方法可以实现这一点,但理想情况下,非常具体地针对您的主/详细流问题,让我们分析默认提供的示例:

ItemDetialActivity 处理片段创建和显示、FAB 和菜单操作。请注意,与用户数据无关,只有“系统”句柄。例如,我尝试限制活动对导航的责任,以及您确实无法避免的事情,例如菜单按钮处理。现在,ItemListActivity 似乎违反了这一原则,因为它负责显示列表(Google 示例只会在这些关注点分离之间造成混淆-恕我直言),我将创建一个单独的片段,其中包含 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;
    }
    ...
}

现在,您应该为每个具体屏幕创建一个从基础派生的演示者、模型和片段,并在那里执行具体操作。希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2016-03-19
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多