我们正在尝试使用(几乎)所有新开发工作中使用的Model-View-Presenter模式.
我坚信有一个框架可以帮助人们满足设计要求,我们有一些内部框架可以用于各种不同的组件(日志记录,电子邮件发送等),所以我试图获得某种MVP框架开发.
我已经设法将一些易于使用的东西放在那些不熟悉MVP并且与我们目前的工作方式相差不远的人身上.问题在于它正在与1个演示者建立1个视图的关系.
这是框架的大致轮廓:
public abstract class Presenter<TView> where TView : IView {
public virtual T View { get; set; }
public virtual void Setup(TView view) {
this.View = view;
}
}
public interface IView { }
Run Code Online (Sandbox Code Playgroud)
它的基本工作方式是创建的任何View都继承自IView接口,并传递给继承自抽象类的PresenterPresenter类.
正如您所看到的,我正在使用.NET泛型,以便开发人员在处理演示者时可以强大地键入View(最后是从演示者继承的类).
所以我可以像这样设置一个基本的登录组件:
public class Login : Presenter<ILogin> {
public override Setup(ILogin view){
base.Setup(view);
this.View.Login += new EventHandler(login);
}
void login(object sender, EventArgs e) { ... }
}
public interface ILogin : IView { …Run Code Online (Sandbox Code Playgroud) 使用MVP,您通常将视图(UI)与Presenter中的Presenter绑定.但是使用最新版本的GWT,特别是使用UIBinding,您可以在视图中执行以下操作:
@UiHandler("loginButton")
void onAboutClicked(ClickEvent event)
{
// my login code
}
Run Code Online (Sandbox Code Playgroud)
这基本上为一些快速注释代码交换了许多匿名内部类代码.非常好!!问题是此代码在视图中而不是演示者...
所以我想也许:
@UiHandler("loginButton")
void onAboutClicked(ClickEvent event)
{
myPresenter.onAboutClicked(...);
}
Run Code Online (Sandbox Code Playgroud)
但是这种方法存在一些问题.最重要的是,您可以模糊View和Presenter之间的界限.谁做了绑定,在某些情况下它是视图,在其他情况下它是演示者(绑定到不在当前视图中但需要附加的事件 - 例如系统范围的更新事件).
您仍然可以获得能够对演示者进行单元测试的好处,但需要付出多少代价.责任现在很混乱.例如,绑定有时在"视图"中,其他时间在"演示者"级别中.随着时间的推移,我可以看到代码陷入各种混乱状态.
我还考虑将Presenter扩展到View,以便您可以在View中执行此操作.这里的问题是你失去了Presenter运行标准单元测试的能力!这是一个重大问题.这和线条再次变得模糊.
所以我的问题是,有没有人有一个很好的方法来利用MVP模式中UIBinding的注释,而不会模糊线条并失去MVP模式的优势?
我的公司正在努力做出有关如何追求未来发展的明智决定.
我们似乎已将我们未来的内部和外部应用程序缩小为Web应用程序.但是从那时起我们仍然有点困惑.
这里有很多对Sharepoint的支持.据我了解,Sharepoint基本上是使用MVP的ASP.NET.
其他人希望使用较新的MVC风格使用普通的ASP.NET.
我也被告知,这些不容易在一起很好地发挥.
它看起来像Sharepoint(和ASP.NET MVP)将成为赢家.在我们走向那个方向之前,我想问:
如果我们选择基于Sharepoint(即ASP.NET和MVP)开展未来5到10年的开发工作,我们放弃了什么?这是一个大问题,还是只是一些我们正在失去的"好东西".
(现在要让管理层改变方向,这将是一个相当大的交易.)
我正在努力将应用程序从Windows Mobile移植到android,我遇到了一些问题.现有的应用程序使用MVP模式并具有不同的"presenter"类,这些类将在端口中重用(它是相当广泛的应用程序并且重写它是不可能的,并且C#代码全部被重用使用mono for android ).这些视图实现了一个接口,在android中我通过创建实现适当接口的活动,实例化一个演示者并将自己作为参数传递来实现.这一切似乎都适合我们的目的,或直到冰淇淋三明治出来,我试图用碎片实现它.
相当多的活动都使用了标签,为了使用操作栏和其他一些新功能,我试图将标签式活动转换为带有viewpager的标签式片段,这就是我遇到的一些问题.从我所看到的,实现每个选项卡作为片段似乎是首选的方法,但我很困惑,我是如何允许演示者通过活动与片段进行通信.目前,演示者调用活动的接口方法,然后直接访问微调器,文本视图等以获取和设置所需的值.由于这些ui元素中的每一个都在活动中声明,这是微不足道的.如果我将所有这些ui元素移动到片段,但是如果不在每个活动和片段之间实现一组全新的接口,我似乎无法访问它们.我已经尝试在活动中为片段中的ui元素生成一个引用(通过获取片段根视图,然后在其中找到我想要的视图),但是viewpager并不总是加载片段,所以这不起作用,即使它已经加载它们,布局也不会膨胀,直到活动处于运行状态,所以我总是得到返回的空值.
我知道这是一个奇怪的问题,但是如何让我的演示者类与现在存储在单独片段选项卡中的ui元素进行交互?我觉得我必须以完全错误的方式解决这个问题,但我只是看不出应该怎么做,所以如果有人能提出一些关于如何做到这一点的建议那就太好了.
我正在处理开发我的应用程序的一个大问题.它是C#上实现Model-View-Presenter模式的Winforms基础应用程序,但我是这个方法的新手.我到处搜索,但没有找到我的问题的答案.
我需要知道如何使用这种模式来允许winforms之间的通信,以及演示者如何在不将演示者与表单耦合的情况下显示它们.我已经看到了使用Factory模式的方法,但是不明白如何实现它.
任何帮助或指向正确的方向将不胜感激.
在开发Android应用程序时,我偶然发现了一个问题.我刚刚开始使用Dagger,所以我知道一些基本概念,但是当在教程范围之外使用它时,它们的用例变得不那么清楚了.
所以要明白这一点.在我的应用程序中,我正在使用MVP,如本博客文章中所述:http://antonioleiva.com/mvp-android/
所以起初我将Interactor类(处理数据的类)注入Presenter类,一切正常.但后来我实现了使用SQLite数据库的方法,所以现在需要在我的Interactor类中使用Context.
我无法弄清楚我该如何正确地做到这一点?我的临时修复是将Dagger从我的应用程序中排除,并在创建Presenter类时在构造函数中传递Context变量,然后在presenter中传递Interactor类,但我想使用Dagger.
所以我目前的应用看起来有点像这样.
MyActivity implements MyView {
MyPresenter p = new MyPresenter(this, getApplicationContext());
}
Run Code Online (Sandbox Code Playgroud)
MyPresenter中的构造函数
MyPresenter(MyView view, Context context) {
this.view = view;
MyInteractor i = new MyInteractor(context);
}
Run Code Online (Sandbox Code Playgroud)
在构造函数中MyInteractor我分配Context给一个私有变量.
我只需要注入MyInteractor来MyPresenter,因为这是应用程序,需要针对不同的实现进行测试的一部分.但是,如果它也将是可以注入MyPresenter到MyActivity,那将是巨大的:)
我希望有人对我想要实现的目标有一些经验:)
我有MVP模式显示的项目列表.View是一个Activity(aka ItemsList).我想显示下一个Activity(也是MVP'ed,aka ItemDetails),点击项目的详细信息ItemsList.
模型ItemsList用来自Repository的数据.实际上它是RMVP.它看起来像这样:
|->Model<->Presenter<->View [ItemsList]
Repository<-|
|->Model<->Presenter<->View [ItemDetails]
Run Code Online (Sandbox Code Playgroud)
所以模型ItemsList已经知道了型号项目被点击了什么,所以我可以通过它从马上ItemsList到ItemDetails不从资源库中获取数据,从数据到模型再次/制图/制造新的模型ItemDetails等.
我应该如何在MVP中的活动之间传递数据(例如,哪个项目被点击)?
解决方案1
使用Intent传递这些数据(类似于此处讨论的那样),但......然后如何处理这些数据?你可以在活动(视图)中从Intent解压缩它,而你应该在MVP的另一端,即在模型中.你把它从View to the Presenter传递给Model吗?
但是,Model in ItemDetails不是从"MVP的下行"(来自Repository)创建的,而是来自"MVP的上层"(来自Presenter).
解决方案2
仅将已点击项目的ID传递给ItemDetailsView(类似于android10/Android-CleanArchitecture在UserDetailsActivity中使用字段提出的内容private int userId;这也是googlecodelabs的NoteDetailPresenter使用的内容)
但是可能有问题因为我可能有两个Repository实现:
ItemDetailsView(但它似乎过度设计),类似于android10/Android-CleanArchitecture在UserDetailsActivity中提出的字段private int userId;ItemsList我是RxJava的新手,并将其与MVP架构结合使用.
我发现了一些关于使用保留片段在配置更改时保存observable的示例(仍然不确定这是否是最好的方法).我发现的例子是直接在Activity或Fragment上处理observable,而不是从Presenter处理.
所以我试验并设置了这个快速示例(仅使用Reactivex的RxJava和RxAndroid lib)来测试,这似乎工作正常.这个例子的作用是:
我想知道我是否正确地执行此操作,并且当在Presenter中处理observable的订阅时,是否有更高效或更优雅的方式来处理配置更改?
编辑:感谢您的反馈.基于此,我已经达到了我认为更清洁的解决方案,并且我已经更新了我的链接示例.
随着新的变化; 而不是将Observable从Presenter传递给Activity到retainFragment以存储一个configurationChange事件,我宁愿将retainFragment设置为Presenter创建时的第二个"视图".
这种方式当onResume()在设备旋转后发生时,我不需要让Activity执行将Observable从retainFragment传递回Presenter的丑陋管道.
Presenter可以直接与第二个"视图"进行交互,并检查保留的observable本身并在需要时重新订阅.主要活动不再需要知道这个可观察的.突然间,这是一个更简单的视图层.
所以我有一个已经与活动相关联的演示者.这本书说一个主持人应该绑在一个视图上.但现在我添加了一些片段和大量自定义视图.我正在考虑一个片段作为一个观点.自定义视图将包含一些逻辑.片段和自定义视图当然都包含在我的活动中.
我的问题是,我应该在片段和自定义视图中重复使用相同的演示者,还是每个视图都应该有自己的演示者?我意识到这是基于意见,但我想要最好的方法来测试和保持代码清洁.
如果我确实为所有这些少数人提供了一个演示者,那么接口演示者使用将有许多回调方法.同时,如果我做了相反的操作并为每个视图创建了一个演示者,那么它可能更容易阅读,但我将如何测试呢?
最近我接手了一个建立在MVP之上的android项目.虽然简单的屏幕非常简单,易于阅读和维护,但应用程序中更复杂的部分却不是.多个继承级别导致我在类之间切换几天,试图找出信息流实际上是如何工作的.
这里是一个更有问题的层次结构的例子:
由于我们使用MVP,因此图中的每个类自然会有另一个presenter类和另一个视图类.
所以我做了一些研究并发现了这篇文章: MVP中的组合与继承 ,它基本上说在这种情况下组合应该优于继承.不说的是如何在android中应用它.我想了一会儿,但不能想出一个漂亮的模式.我可以做自定义视图,但他们最终会如何使用演示者?
mvp ×10
android ×6
.net ×1
architecture ×1
asp.net ×1
asp.net-mvc ×1
dagger ×1
fragment ×1
gwt ×1
java ×1
rx-android ×1
rx-java ×1
sharepoint ×1
views ×1
winforms ×1