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

How to pass data from parent view's presenter to child view's presenter?

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

Activity - Presenter
    |
Fragment
    |
CustomView
    |
  views

所以当presenter从网络获取数据时,直接传数据给fragment,fragment传数据给自定义视图,自定义视图传数据给视图。

我不确定如何使用 MVP 模式传递来自 activity 的视图中使用的数据。如果我为每个片段、自定义视图和视图创建演示者,那么如何将数据从 activity 的演示者传递给其他演示者? 谁能帮我举个例子?

为了更具体地回答您的问题,您需要举一个具体的例子。每个解决方案在 context 中都是有效的。我将提供几种方法供您执行此操作。选择适合您的问题。

MVP 非常重要的部分是 模型。据我所知,术语 Model 随着论文 Thing Model View Editor 的发布而在编程中变得流行,后来被提炼和重命名为 MVC。

论文中一个模型的概念定义是:

A Model is an active representation of an abstraction in the form of data in a computing system

The Models are represented in the computer as a collection of data together with the methods necessary to process these data.

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

以下是其中的一些:

MVP,由于是从MVC派生出来的,所以做了两大职责划分:Model表示概念的抽象)和PresentationView and Presenter 可视化 模型).

因为我们已经将ModelPresentation[中分离出来了=171=],我们可以有多个 Views 显示相同的 Model 不同的方式。一个例子是 Model 表示 Statistical Data 可以以不同的方式显示:饼图、条形图等。在此示例中,统计数据模型领域模型.

在上面的例子中,模型可能会在两个[之间共享=284=]对PieChart条形图。如果您使用 Observer pattern,当 View-Presenter 对之一 更新 StatisticalModel,它会引发变化的事件,View-Presenter对都会收到此更改和更新的通知。

有时应用程序需要 ApplicationModel。该模型可以在不同的 View-Presentation 对 之间共享。我们来看一个 verfy 简化的 示例。

假设我们有一个文件浏览器应用程序,例如 Windows Explorer。该应用程序的 GUI 有两个主要部分:显示文件夹的 Tree 的左侧面板和中间的 File-Folder 面板。在左侧文件夹树面板中选择文件夹时,所选文件夹中的文件和文件夹必须显示在中间面板中。我们可以通过定义一个 ApplicationModel 来做到这一点,它将捕获和表示上述逻辑并在 [=57= 之间共享]View-Presentation 对 用于左侧和中间面板。

注意:我将省略细节以简化示例并减少代码

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 class 是 Model 的一部分 并且是一个 应用程序模型。因为它是共享的并且它的生命周期与应用程序相同(只要应用程序是 运行 它就存在)它将保持状态。 ViewsPresenters 被创建和销毁,但这class 将存在并保持状态,因此当一个新的 View and/or Presenter 已创建,它可以检查此状态并执行某些操作。

根据我的经验,人们确实更多地关注 Views 和 Presenter,而他们应该专注于 Models。我个人经常使用 Models,因为它让事情变得更清晰,应用程序更容易理解。

当然,使用 Models 并不总是有效,所以当它们不起作用时,您可以使用 messaging,有一个 Presenter 向其他人发送消息。这是使用相同文件浏览器应用程序的示例。

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 从而创建对 Model 的依赖从 Presenters 而不是创建依赖关系 between Presenters 。这样你就有了松耦合ng 在 Presenters 之间,您可以更轻松地更改它们

如果您不能使用 Model,请使用 Messages。通过创建 protocol[=171= 来解耦 Presenters 是一种很好的方式] 用于通信的消息。

查看 this 有关使用消息进行组件间协作的文章。

这里还有一些关于 GUI 架构的好文章: