Android MVP - 在View实现(Fragment或Activity)中调用View方法

3
我在新应用程序中实现MVP,遇到一个问题。我需要在ViewActivity)本身内部调用View的一个方法。按照MVP代码分离的定义,这是错误的做法。
根据定义:
Presenter负责Model和View之间的协调。它基本上接收来自两者的事件并相应地行动。Presenter是唯一知道其他组件的组件。它有对View的引用和对Model的另一个引用。(来源source)
在同一篇文章中提到,View不会对用户交互做出反应,它将控制权交给Presenter来完成工作。我还阅读了this SOF post关于依赖规则的内容。
在我的情况下,我正在使用自定义的 AppTheme。需要在调用 setContent() 之前设置 AppTheme,我创建了一个名为 setAppTheme() 的方法,并将其添加到 View 接口中,由我的 Activity 实现,并在其中添加应用主题的代码。现在问题是,在应用内部调用这个方法会导致在其实现中调用 View 方法。
总之,我对MVP的理解是以下两者之一应该成立:
1. 在Activity中调用View方法,因为setTheme()在setContent()后无法使用,而我们的presenter.setView()在onResume()中,但这是否满足MVP的M-V-P分离?
2. 不要为setAppTheme()创建接口方法,而是在Activity中创建一个私有方法来设置主题。这个方法与MVP的任何层都没有关系。但问题是,如果项目使用MVP模式,这种做法是否有效?
这是我的MVP:
public class AboutUsMVP
{

    public interface Model
    {


        String getFbLink();
        String getTwitterLink();
        String getEmailLink();
        String getCompanyLink();

    }

    public interface Presenter
    {
        void setView( View view );

        void fbButtonClicked();

        void twitterButtonClicked();

        void emailButtonClicked();

        void imageButtonClicked();

    }

    public interface View
    {

        void showFacebookPage();
        void showTwitterPage();
        void showEmailIntent();
        void showCompanyWebsite();
        void setAppTheme();
        void setCustomActionBar();

    }

}

请您指出我可能疏漏的错误。

据我所知,同样可以通过 setActionBar()setOnClickListener() 方法来讨论同一情况,尽管这些方法可能需要单独的帖子,但它们在这里更为相关,而且对它们的任何新帖子都将是重复的。

请注意,我的Activity实现了View接口。

编辑:更多说明

我的View实际上是Activity类。这是MVP的View,而不是Android API的View类。问题是,有一个方法setAppTheme(),它只与MVP的View(Android的Activity)相关。这个调用不在合同(AboutUsMVP.java)中,根据Google的惯例应该是AboutUsContract.java,这个setAppTheme()不在合同中,也不能在合同中,那么这是否违反了MVP原则?

没有可能的替代方案,可以说是制作setAppTheme()的接口,但如果我这样做,它将无法工作,因为:

setAppTheme()方法在调用super()方法后立即调用,否则将无效。MVP的Presenter在onResume中开始工作。如果创建了一个接口,并将setAppTheme()带入MVP的范围内,则它将没有任何效果。


你的主题是否是基于用户交互的动态主题?否则为什么不直接在清单文件中设置主题呢?我对MVP也很新,但我认为在onCreate中调用Presenter来初始化View(即你的setView()),然后Presenter调用setAppTheme是正确的。在presenter.setView()之后,你可以像平常一样调用setContentView - Eselfar
是的,用户可以在应用程序运行时更改主题,并且它将保存在一致的存储中。 - Talha
1
你可以从这里获取到我关于MVP的相关代码:https://github.com/saveendhiman/SampleApp/tree/master/app/src/main/java/com/sampleapp/module/fragmentsample - Saveen
如果你在寻找Kotlin相关内容,请前往https://github.com/saveendhiman/SampleAppKotlin。 - Saveen
会看一下。 - Talha
2个回答

3

实际上,在MVP中,View应该是“愚笨的”,也就是说,它们不包含任何逻辑内容。只需接收用户生成的事件并立即将其工作委托给Presenter。 View还可以通知Presenter一些事件已发生(例如视图已创建,屏幕旋转等)

这可能会导致一些混淆。谁负责调用某些方法?正如您所说,View需要执行一些动作,例如setOnClickListener,但是Presenter负责处理事件。请记住以下内容:

View只是一个接口。这意味着您可以使用实现该接口的任何东西

现在您正在开发移动应用程序。但是,如果您想编写控制台或桌面应用程序,则演示逻辑不会改变。任何特定于“View技术”的内容(Android、桌面等)都应在特定于该技术的代码内执行。这样,您的代码将与技术栈松散耦合。


任何与“视图技术”(Android、桌面等)有关的内容都应在特定于该技术的代码内执行。我的视图实际上是Activity类。这是MVP的视图,而不是Android API的View类。问题是,有一个名为setAppTheme()的方法,它仅与MVP的视图(Android的Activity)相关。此调用不在合同(AboutUsMVP.java)中,根据Google的惯例,应该是AboutUsContract.java,这个setAppTheme()不在合同中,也不能在合同中,那么这是否违反了MVP原则?请参见编辑:更多解释。 - Talha
1
当我说“View”时,我总是指的是您使用的任何UI。如果您的代码是针对Android特定的,则应将其放在活动中。如果您的代码仅涉及表示逻辑,请将其放在Presenter中。 - Alberto S.

1
我相信@Pelocho的答案是正确的,您应该将其标记为正确答案。但是,我想从另一个角度提出我的答案(与他的意见相同)。对于这个不同的观点,我想就您对Presenter的定义进行辩论:
“Presenter负责模型和视图之间的协调。”
因此,我在这里提出的问题是:“Presenter与之交互的模型是什么?” 我的回答是查看经典的“笔记”应用程序,并认为模型是文本和相关元数据,通常存储在某个数据库中,Presenter将读取、解析并推送到视图中。
在这个“模型”中,应用程序主题无关紧要。主题纯粹是视图的功能。主题仅与最终屏幕外观相关联。就像视图负责在屏幕上布局内容或知道要使用什么字体大小一样。
这意味着即使可以从用户设置选项更改这些布局、大小、颜色,它们仍然超出了Presenter和Model的责任范围,因为它们只关心内容。
简而言之:

只需直接从SharedPreferences中读取Activity.onCreate主题(在super.onCreate之前),不涉及Presenter。


1
如果这是你对“Presenter”的定义……也许你正在使用MVC而不是MVP。因为这是“Controller”的定义。Presenter负责展示逻辑。 - Alberto S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接