我的 MVP 实施模式有效吗?
Is my implementation pattern for MVP valid?
我是 Android 和一般 MVP 的新手,在过去的 1.5 年里我一直在进行 iOS 编程,所以我发现委托模式很容易理解。我以视图符合演示者协议的方式实现了 MVP,这让演示者忽略了视图的特定类型,但让它知道某些方法是给定的,因此可以调用 "view."我一直在阅读各种 MVP 指南和所有 Mosby 教程,但我不确定我是否同意其中的一些内容。我实施的模式是否符合犹太洁食标准?我想要一些反馈,这样我就不会一直朝着错误的方向前进,如果这确实是我正在做的......
例如,
基地主持人:
public abstract class Presenter<V, S> implements BasePresenterInterface<V, S> {
public interface PresenterProtocol extends BasePresenterProtocol {
}
private WeakReference<V> mAttachedView = null;
private S mService = null;
/**
* Interface Overrides
*/
@Override
public void attachView(V view) {
boolean viewDoesNotConform = !viewDoesConform(view);
if (viewDoesNotConform) {
Log.d("DEBUG", "Cannot attach View that does not conform to PresenterProtocol");
return;
}
mAttachedView = new WeakReference<>(view);
((BasePresenterProtocol) getAttachedView()).onViewAttached();
}
@Override
public void detachView() {
mAttachedView = null;
}
@Override
public boolean viewDoesConform(V view) {
Class<?> klass = view.getClass();
boolean conforms = BasePresenterInterface.BasePresenterProtocol.class.isAssignableFrom(klass);
return conforms;
}
@Override
public boolean viewIsAttached() {
return mAttachedView != null;
}
@Override
public V getAttachedView() {
return mAttachedView.get();
}
@Override
public S getService() {
return mService;
}
@Override
public void setService(S service) {
mService = service;
}
}
然后我将其子类化为以下内容:
PhotoRecyclerPresenter:
public class PhotoRecyclerPresenter extends Presenter<PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol, PhotoService> {
public interface PhotoRecyclerPresenterProtocol extends Presenter.PresenterProtocol {
void onPhotosLoaded(List<TestPhoto> photoList);
void onItemSelected(TestPhoto photo);
void onShowDetail(TestPhoto photo);
}
private static PhotoRecyclerPresenter mSharedInstance;
private PhotoRecyclerPresenter() {
setService(new PhotoService());
}
/**
* External Methods
*/
public void getPhotos() {
boolean noAttachedView = !viewIsAttached();
if (noAttachedView) {
Log.d("DEBUG", "No view attached");
return;
}
getService().getAPI()
.getPhotos()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoList -> getAttachedView().onPhotosLoaded(photoList));
}
/**
* Internal Methods
*/
public static PhotoRecyclerPresenter getSharedInstance() {
boolean firstInstance = mSharedInstance == null;
if (firstInstance) {
setSharedInstance(new PhotoRecyclerPresenter());
}
return mSharedInstance;
}
public static void setSharedInstance(PhotoRecyclerPresenter instance) {
mSharedInstance = instance;
}
public void didSelectItem(TestPhoto photo) {
getAttachedView().showDetail(photo);
}
}
它与视图通信:
PhotoRecyclerFragment:
public class PhotoRecyclerFragment extends Fragment implements PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private Activity mParentActivity;
private PhotoRecyclerPresenter mPresenter;
private PhotoRecyclerAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recycler, container, false);
mParentActivity = getActivity();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(mParentActivity);
mAdapter = new PhotoRecyclerAdapter(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mPresenter = PhotoRecyclerPresenter.getSharedInstance();
mPresenter.attachView(this);
return rootView;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mPresenter.detachView();
mAdapter.clear();
}
/**
* PhotoRecyclerPresenterProtocol Methods
*/
@Override
public void onItemSelected(TestPhoto photo) {
mPresenter.didSelectItem(photo);
}
@Override
public void onPhotosLoaded(List<TestPhoto> photoList) {
mAdapter.loadPhotos(photoList);
}
@Override
public void onViewAttached() {
mPresenter.getPhotos();
}
@Override
public void onViewDetached() {
}
@Override
public void onShowDetail(TestPhoto photo) {
Intent detailIntent = new Intent(mParentActivity, PhotoDetailActivity.class);
mParentActivity.startActivity(detailIntent.putExtra(Intent.EXTRA_UID, photo.getPhotoId()));
}
}
这让我可以定义一组视图需要遵守的要求,以便使用单例演示器,同时让演示器不知道使用它的视图,只要它们符合其协议。到目前为止,在我的实践项目中它似乎工作正常,但我似乎无法找到任何资源,就 MVP 而言,推荐我正在做的事情,而且我有足够的自我怀疑,我想我会问我的第一个 Whosebug 问题。任何有 MVP 经验的人都可以对此有所了解吗?
此外,如果我问错了地方,请随时指出 post 这个问题的正确位置。
谢谢:)
在我看来,您正在做与莫斯比所做的相同的事情。唯一的区别是接口(或 objective-c 中的协议)世界的名称。你称它为 PresenterProtocol
,而 Mosby 称它为 MvpView
。两者都在做同样的工作:提供 Presenter
和 Api 演示者可以调用的方法来操纵视图。
唯一没有意义的是有一个方法viewDoesConform()
。在 Java 你有类型安全。您可以使用 Presenter 的泛型类型 V
来确保您的片段正在实现 Presenter 的协议。只需将其更改为 V extends BasePresentersProtocol
此外,我认为主持人的 "shared instance"(a.k.a 单例模式)没有意义。我认为拥有 PhotoService 的 "shared instance" 会更有意义。但是但也请注意,这样做您的代码将不再可测试(单元测试)。您应该 google 了解依赖注入或逆向控制,以了解如何编写模块化、可重用和可测试的代码。我不是在谈论像 Dagger、spring 或 guice 这样的依赖注入框架。您只需要了解依赖注入背后的想法即可。您可以完全遵循此原则编写 类,而无需依赖注入框架(即使用构造函数参数)。
旁注:您永远不会取消您的演示者对 PhotoService 的订阅。根据 PhotoService 的实现方式,您可能会发生内存泄漏,因为 PhotoService observable 具有对演示者的引用,这会阻止演示者和 PhotoService(取决于您的具体实现)被垃圾收集。
编辑:Mosby 定义了视图的协议。查看项目网站上的入门部分。 HelloWorldView
定义了两个方法:showHello()
和showGoodbye()
(由HelloWorldActivity
实现),HelloWorldPresenter
调用这两个方法来操作View。 HelloWorldPresenter
也取消异步请求以避免内存泄漏。你也应该这样做。否则你的演示者只能在改造 httpcall 完成后被垃圾收集。
我是 Android 和一般 MVP 的新手,在过去的 1.5 年里我一直在进行 iOS 编程,所以我发现委托模式很容易理解。我以视图符合演示者协议的方式实现了 MVP,这让演示者忽略了视图的特定类型,但让它知道某些方法是给定的,因此可以调用 "view."我一直在阅读各种 MVP 指南和所有 Mosby 教程,但我不确定我是否同意其中的一些内容。我实施的模式是否符合犹太洁食标准?我想要一些反馈,这样我就不会一直朝着错误的方向前进,如果这确实是我正在做的......
例如,
基地主持人:
public abstract class Presenter<V, S> implements BasePresenterInterface<V, S> {
public interface PresenterProtocol extends BasePresenterProtocol {
}
private WeakReference<V> mAttachedView = null;
private S mService = null;
/**
* Interface Overrides
*/
@Override
public void attachView(V view) {
boolean viewDoesNotConform = !viewDoesConform(view);
if (viewDoesNotConform) {
Log.d("DEBUG", "Cannot attach View that does not conform to PresenterProtocol");
return;
}
mAttachedView = new WeakReference<>(view);
((BasePresenterProtocol) getAttachedView()).onViewAttached();
}
@Override
public void detachView() {
mAttachedView = null;
}
@Override
public boolean viewDoesConform(V view) {
Class<?> klass = view.getClass();
boolean conforms = BasePresenterInterface.BasePresenterProtocol.class.isAssignableFrom(klass);
return conforms;
}
@Override
public boolean viewIsAttached() {
return mAttachedView != null;
}
@Override
public V getAttachedView() {
return mAttachedView.get();
}
@Override
public S getService() {
return mService;
}
@Override
public void setService(S service) {
mService = service;
}
}
然后我将其子类化为以下内容:
PhotoRecyclerPresenter:
public class PhotoRecyclerPresenter extends Presenter<PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol, PhotoService> {
public interface PhotoRecyclerPresenterProtocol extends Presenter.PresenterProtocol {
void onPhotosLoaded(List<TestPhoto> photoList);
void onItemSelected(TestPhoto photo);
void onShowDetail(TestPhoto photo);
}
private static PhotoRecyclerPresenter mSharedInstance;
private PhotoRecyclerPresenter() {
setService(new PhotoService());
}
/**
* External Methods
*/
public void getPhotos() {
boolean noAttachedView = !viewIsAttached();
if (noAttachedView) {
Log.d("DEBUG", "No view attached");
return;
}
getService().getAPI()
.getPhotos()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoList -> getAttachedView().onPhotosLoaded(photoList));
}
/**
* Internal Methods
*/
public static PhotoRecyclerPresenter getSharedInstance() {
boolean firstInstance = mSharedInstance == null;
if (firstInstance) {
setSharedInstance(new PhotoRecyclerPresenter());
}
return mSharedInstance;
}
public static void setSharedInstance(PhotoRecyclerPresenter instance) {
mSharedInstance = instance;
}
public void didSelectItem(TestPhoto photo) {
getAttachedView().showDetail(photo);
}
}
它与视图通信: PhotoRecyclerFragment:
public class PhotoRecyclerFragment extends Fragment implements PhotoRecyclerPresenter.PhotoRecyclerPresenterProtocol {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private Activity mParentActivity;
private PhotoRecyclerPresenter mPresenter;
private PhotoRecyclerAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recycler, container, false);
mParentActivity = getActivity();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(mParentActivity);
mAdapter = new PhotoRecyclerAdapter(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mPresenter = PhotoRecyclerPresenter.getSharedInstance();
mPresenter.attachView(this);
return rootView;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mPresenter.detachView();
mAdapter.clear();
}
/**
* PhotoRecyclerPresenterProtocol Methods
*/
@Override
public void onItemSelected(TestPhoto photo) {
mPresenter.didSelectItem(photo);
}
@Override
public void onPhotosLoaded(List<TestPhoto> photoList) {
mAdapter.loadPhotos(photoList);
}
@Override
public void onViewAttached() {
mPresenter.getPhotos();
}
@Override
public void onViewDetached() {
}
@Override
public void onShowDetail(TestPhoto photo) {
Intent detailIntent = new Intent(mParentActivity, PhotoDetailActivity.class);
mParentActivity.startActivity(detailIntent.putExtra(Intent.EXTRA_UID, photo.getPhotoId()));
}
}
这让我可以定义一组视图需要遵守的要求,以便使用单例演示器,同时让演示器不知道使用它的视图,只要它们符合其协议。到目前为止,在我的实践项目中它似乎工作正常,但我似乎无法找到任何资源,就 MVP 而言,推荐我正在做的事情,而且我有足够的自我怀疑,我想我会问我的第一个 Whosebug 问题。任何有 MVP 经验的人都可以对此有所了解吗?
此外,如果我问错了地方,请随时指出 post 这个问题的正确位置。
谢谢:)
在我看来,您正在做与莫斯比所做的相同的事情。唯一的区别是接口(或 objective-c 中的协议)世界的名称。你称它为 PresenterProtocol
,而 Mosby 称它为 MvpView
。两者都在做同样的工作:提供 Presenter
和 Api 演示者可以调用的方法来操纵视图。
唯一没有意义的是有一个方法viewDoesConform()
。在 Java 你有类型安全。您可以使用 Presenter 的泛型类型 V
来确保您的片段正在实现 Presenter 的协议。只需将其更改为 V extends BasePresentersProtocol
此外,我认为主持人的 "shared instance"(a.k.a 单例模式)没有意义。我认为拥有 PhotoService 的 "shared instance" 会更有意义。但是但也请注意,这样做您的代码将不再可测试(单元测试)。您应该 google 了解依赖注入或逆向控制,以了解如何编写模块化、可重用和可测试的代码。我不是在谈论像 Dagger、spring 或 guice 这样的依赖注入框架。您只需要了解依赖注入背后的想法即可。您可以完全遵循此原则编写 类,而无需依赖注入框架(即使用构造函数参数)。
旁注:您永远不会取消您的演示者对 PhotoService 的订阅。根据 PhotoService 的实现方式,您可能会发生内存泄漏,因为 PhotoService observable 具有对演示者的引用,这会阻止演示者和 PhotoService(取决于您的具体实现)被垃圾收集。
编辑:Mosby 定义了视图的协议。查看项目网站上的入门部分。 HelloWorldView
定义了两个方法:showHello()
和showGoodbye()
(由HelloWorldActivity
实现),HelloWorldPresenter
调用这两个方法来操作View。 HelloWorldPresenter
也取消异步请求以避免内存泄漏。你也应该这样做。否则你的演示者只能在改造 httpcall 完成后被垃圾收集。