我想创建一个具有嵌套水平RecyclerView
的垂直RecyclerView
的应用。在这种情况下,我不明白如何正确使用MVP模式。 MVP"规则"说它应该只是一个屏幕视图。
我的View
界面:
public interface ViewLayer {
void showProductsInCategory(int categoryId, List<ProductModel> productList, PresenterLayer presenter);
void showCategories(List<CategoryModel> categoryItemList, PresenterLayer presenter);
}
主讲人:
public interface PresenterLayer {
void onViewReady();
}
型号:
public interface InteractorLayer {
void getProducts(int categoryId);
void getCategories();
}
模型监听器接口:
public interface InteractorListener {
void onProductsLoaded(int id, List<ProductModel> products);
void onCategoriesLoaded(List<CategoryModel> categories);
}
CategoryModel:
public class CategoryModel {
private String categoryName;
private List<ProductModel> productList;
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public List<ProductModel> getProductList() {
return productList;
}
public void setProductList(List<ProductModel> productList) {
this.productList = productList;
}
}
所以我必须通过RecyclerView
选择每个嵌套categoryId
来将数据添加到其适配器。我可以为每个水平RecyclerView
?
UPD:
一步一步
1)MainActivity.onCreate
来电presenter.onViewReady()
2)演示者调用interactorLayer.getCategories()
3)模型调用InteractorListener.onCategoriesLoaded(List<CategoryModel> categories)
4)演示者调用ViewLayer
(MainActivity
)showCategories(List<CategoryModel> categoryItemList, PresenterLayer presenter)
5)MainActivity
将categoryItemList
设置为外部RecyclerView
的适配器。现在每个categoryItem都有null
productList
6)在onCategoriesLoaded(...)
Presenter在每个类别的周期中调用模型ViewLayer.showCategories(...)
之后的方法InteractorLayer.getProducts(i)
中
7)在productList
次Presenter
次来电ViewLayer
showProductsInCategory(...)
MainActivity
8)Adapter
获取主RecyclerView
的{{1}},获取一个类别项并为其设置productList
。
9)MainActivity
来电Adapter
&#39; s notifyDataSetChanged()
10)当RecyclerView
调用
productList
设置新的onBinding
我觉得它非常复杂。我该怎么办?
UPD 03/24/2017
答案 0 :(得分:4)
首先,我想说的是,我并不认为自己是MVP大师,而是一个努力理解模式的人,
我最喜欢的MVP参考:来自Uncle Bob博客的The Clean Architecture
根据这篇博文,有一些名为依赖规则:
... 源代码依赖只能指向内部。内圈中没有任何东西可以对外圈中的某些东西一无所知......
例如,Presenter
课程不需要了解RecyclerView
或RecyclerView.Adapter
的任何内容。它需要一些interface
来将信息传递给外层。
interface
的方法取决于用例:使用List
,希望能够
List
(showCategories()
)
showProductsInCategory()
)
所以我认为依赖规则说,ViewLayer
接口必须提供满足[模型层和 Presenter 需求的方法层。作为演示者,我根本不在乎查看是否有ListView
或者根本不是View
而是而是声音和振动信号的某种组合。
另一方面,View
类似乎完全可以知道其Presenter
类的名称(和方法),所以PresenterLayer
接口可能不是必须具备的。
完全取决于查看如何向用户提供数据。嵌套的View
结构仍然只是一个复杂的View
。所以我没有&#39;认为需要提供嵌套的interface
s。
在某些使用嵌套List
的情况下,Presenter
可能需要一种方法来更新内部List
的内容,例如showSingleProductInCategory(ProductModel product, int categoryPosition, int productPosition)
。
另一个有趣的问题:谁保留(并可能修改)数据?在我看来, Presenter 负责数据,它只应将对数据的引用传递到视图层或通知它更改。适配器不应该有权修改原始数据列表,Presenter永远不应该问适配器&#34;有多少项?&#34;而且我不太喜欢两个单独数据列表的想法。各种通知......方法的名称似乎表明我在那里的正确轨道。
这意味着Presenter
将始终保留原始数据List
。如果数据发生变化,Presenter
将更新其数据(可能是clear()
和&#34;复制新项目&#34;也可能更细粒度,具体取决于{{1} }提供)之后,ProductLoader
将通过Presenter
界面通知Adapter
。
链接到zip file with the modified Java classes
编辑
不知何故,我怀疑一个屏幕&#34;一个查看。适用于Android。想象一下典型的Master-Detail情况。如果屏幕很大,您将需要使用空格并同时显示ViewLayer
个。
因此,如果每Fragment
有一个查看(以及一个演示者),一切都适用于所有类型的屏幕。它取决于屏幕尺寸,由Fragment
来管理Activity
。
我已经解释过,我希望某些Fragment
或Adapter
的{{1}}实现ListView
作为{的回调所需的RecyclerView
{1}}。 (作为回调角色的所有interface
都可以将信息传递给Presenter
无论如何)
另一方面,Fragment
可能包含几组数据。其中一些可能以某种方式相关(如某个特定艺术家的所有歌曲),其他(所有这些广告......)而不是。 演示者需要方法来告诉查看向用户显示的内容:艺术家的一种方法,广告的一种方法等。
因此,如果我的应用程序包含少量Adapter
个,则Fragment
将包含
Fragment
...而interface
会期望某个类在其void showAdvertisement(AdObject ad);
void showArtistInfo(Artist artist);
中实现此特定Presenter
。 (加上歌曲的interface
),我Constructor
为所有非收藏数据实施Adapter
。
在包含多个应用的项目中,可以考虑使用通用Fragment
(一个用于任何类型的详细信息,一个用于收集)。然后会有一个方法interface
,上面示例中的interface
会期望广告的一个回调和艺术家信息的回调:
showData(T data)
然后在Presenter
中写一个:
MyPlaylistPresenter (DetailInterface<AdObject> adCallback, DetailInterface<Artist> artistCallback, CollectionInterface<Song> songsCallback){...}
有点像Lego :),但总共少于Fragment
个类。并且基本相同的方法在整个项目中具有相同的名称,因此我认为它有助于可维护性。
现在谈谈你的另一个问题:
如果您的应用在客户端有模型,那么我认为您是对的。 另一方面,有些项目中模型是后端的一部分。然后 Presenter 将是合理的选择。