如何将数据从父视图的演示者传递到子视图的演示者?

时间:2019-04-23 00:05:13

标签: android mvp

我正在Android中使用MVP模式。结构如下所示。

Activity - Presenter
    |
Fragment
    |
CustomView
    |
  views

因此,当演示者从网络获取数据时,它将直接将数据传递给片段,然后将片段传递数据传递给自定义视图,并将自定义视图传递数据传递给视图。

我不确定如何使用MVP模式传递活动视图中使用的数据。如果我为每个片段,自定义视图和视图创建演示者,那么如何将数据从活动演示者传递给其他演示者? 有人可以帮我举例吗?

1 个答案:

答案 0 :(得分:1)

为了给您的问题一个更具体的答案,您需要举一个具体的例子。每个解决方案在 上下文 中均有效。我将提供几种方法来实现此目的。选择一个适合您的问题。

MVP 的非常重要的部分是 模型 。据我所知,术语 Model 在论文Thing Model View Editor的发布中在编程中很流行,该论文后来被完善并重命名为MVC。

本文中 模型 的概念定义为:

  

模型 抽象 的有效表示形式,其形式为   计算系统中的数据

     

模型 在计算机中表示为数据的集合   以及处理这些数据所必需的方法

随着时间和经验的积累,人们发现并指定了不同类型的模型。

其中一些是

MVP (由于它是从MVC派生而来的)进行了两个主要的职责划分: 模型 代表概念的抽象< / em>)和 演示文稿 查看和演示者以可视化 模型 ))

由于我们已将 模型 演示文稿 相除,所以我们可以乘以 显示相同 模型 的>视图 。例如,表示 统计数据 模型 可以用不同的方式显示:饼图,柱状图等。在此示例中, 统计数据模型 域模型

在上面的示例中, 模型 可能会在两个 View-Presenter对 之间共享, PieChart BarChart 。如果您使用Observer pattern,则当 视图展示者对之一 更新 StatisticalModel 时,它将引发更改的事件,并且两个 View-Presenter对 都会收到有关此更改和更新的通知。

有时应用程序需要 ApplicationModel 。此模型可以在不同的 视图-展示对 之间共享。让我们看一个非常简单的示例。

假设我们有一个文件浏览器应用程序,例如Windows资源管理器。该应用程序的GUI有两个主要部分:左侧面板显示文件夹的 Tree ,中间面板显示文件文件夹面板。在左侧文件夹树面板中选择一个文件夹时,所选文件夹中的文件和文件夹必须显示在中间面板中。我们可以通过定义 ApplicationModel 来做到这一点,该模型将捕获并表示上述逻辑,并在两个 View-Presentation对 < / strong>(左侧面板和中间面板)。

注意:我将省略该示例的详细信息,并减少代码量

public class ApplicationState {

    // singleton, it's evil I know, 
    // but it's the simplest way without DI or ServiceLocator
    private static ApplicationState mInstance = new ApplicationState();
    public static ApplicationState getInstance() { return mInstance; }

    private Folder mSelectedFolder;

    public bool hasSelectedFolder() { return mSelectedFolder != null; }

    public Folder getSelectedFolder() { return mSelectedFolder; }

    public Folder setSelectedFolder(Folder f) {
        mSelectedFolder = f;
        RaiseSelectedFolderChangedEvent();
    }

    // method for registering listeners, raising events etc.
}

public class FoldersTreeViewPresenter {

    private ApplicationState mApplicationState;

    public void onSelectFolder(FolderView view) {
        // select the folder in the view
        mApplicationState.setSelectedFolder(view.Folder);
    }
}

public class FilesFoldersViewPresenter : ApplicationStateListener {

    private ApplicationState mApplicationState;

    public FilesFoldersViewPresenter() {

        // you can use service locator, dependency injection, whatever
        mApplicationState = ApplicationState.getInstance();

        mApplicationState.addEventListener(this);
    }

    private void getFilesAndFoldersFromFileSystem(Folder folder) {
        // get from fs
        // fill views with them etc.
    }

    private void clearView() { 
        // clear the panel
    }

    public void onApplicationStateChanged() {

        if(mApplicationState.hasSelectedFolder()){
            getFilesAndFoldersFromFileSystem(mApplicationState.getSelectedFolder());
        }
        else {
            clearView();
        }
    }
}

在此示例中,我们创建了一个共享对象,该对象表示应用程序状态和逻辑,即我们的应用程序具有可以更改的选择。在这种情况下, ApplicationState 类是 Model 的一部分,并且是 Application Model 。因为它是共享的,并且其生命周期与应用程序相同(只要应用程序正在运行,它就存在),它将保持状态。创建并销毁了 视图 Presenters ,但是此类将存在并保持状态,因此当创建新的 查看 和/或 Presenter ,它可以检查此状态并执行某些操作。

在我的经验中,人们确实更专注于“视图”和“演示者”,而他们应该使用其 模型 。我经常使用 Models ,因为它可以使事情变得更整洁,并使应用程序更易于理解。

当然,使用 模型 并不总是有效,因此,当它们不起作用时,您可以使用 消息 ,让一个 演示者 向其他人发送消息。这是具有相同文件浏览器应用程序的示例。

public class MessageBus {
    // static this time, you can use DI or ServiceLocator with interface
    public static void sendMessage(object m) { }
    public static void registerListener(MessageListener listener) { }
}

public class FoldersTreeViewPresenter {

    public void onSelectFolder(FolderView view) {
        // select the folder in the view
        MessageBus.sendMessage(new FolderSelected(view.Folder));
    }
}

public class FilesFoldersViewPresenter : MessageListener {

    public FilesFoldersViewPresenter() {
        MessageBus.addListener(this);
    }

    private void getFilesAndFoldersFromFileSystem(Folder folder) {
        // get from fs
        // fill views with them etc.
    }

    public void onMessage(object m) {

       if(m instanceof FolderSelected) {

            FolderSelected folderSelectedMessage = (FolderSelected)m;

            getFilesAndFoldersFromFileSystem(folderSelectedMessage.Folder);
       }
    }
}

根据您的具体情况,如果可以创建一个不错的 模型 (域,应用程序或演示文稿),请执行此操作。共享此 Model ,从而从 Presenters 中创建对 Model 的依赖> ,而不是在 Presenters 之间创建依赖关系。这样,您可以在 Presenters 之间松散耦合,并且可以更轻松地进行更改

如果您不能使用 模型 ,请使用 消息 。通过创建用于通信的消息的 协议 ,这是使 Presenters 脱钩的好方法。

查看this文章,内容涉及使用消息在组件之间进行协作。

这里还有一些关于GUI体系结构的好文章: