我的MVP实施模式是否有效?

时间:2015-09-16 19:30:33

标签: android protocols mvp presenter mosby

我是Android和MVP的新手,我在过去的1。5年里一直在做iOS编程,所以我发现委托模式很容易消化。我已经以这样的方式实现MVP:视图符合演示者的协议,这使得演示者可以忽略视图的特定类型,但是让它知道某些方法是给定的,因此可以调用“视图”。我一直在阅读各种MVP指南,以及所有的Mosby教程,我不确定我是否同意其中的一些内容。我实施犹太教的模式是什么?我想要一些反馈,所以我不会继续走向糟糕的方向,如果那确实是我正在做的......

例如,

Base Presenter:

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而言,我有足够的自我怀疑,我想我会问我的第一个StackOverflow问题。任何有MVP经验的人都可以对此有所了解吗?

另外,如果我在错误的地方提问,请随时将我指向正确的位置发布。

谢谢:)

1 个答案:

答案 0 :(得分:0)

从我的观点来看,你正在做与莫斯比相同的事情。唯一的区别是接口的名称(或objective-c中的协议)世界。您将其称为PresenterProtocol,而Mosby将其称为MvpView。两者都做同样的工作:提供Presenter Api方法,演示者可以调用它来操纵视图。

唯一没有意义的是拥有方法viewDoesConform()。在Java中,您具有类型安全性。您可以使用Presenter的泛型类型V来确保您的片段正在实现Presenter的协议。只需将其更改为V extends BasePresentersProtocol

即可

此外,我认为拥有一个&#34;共享实例&#34;是不合理的。演示者的(a.k.a Singleton模式)。我认为拥有一个共享实例会更有意义。的PhotoService。但是请注意,通过这样做,您的代码不再可测试(单元测试)。您应该google for Dependency injection或Inverse of Control来了解如何编写模块化,可重用和可测试的代码。我不是在谈论依赖注入框架,如Dagger,spring或guice。你应该理解依赖注入背后的想法。您可以完全遵循此原则编写类,而无需依赖注入框架(即使用构造函数参数)。

附注:您永远不会从PhotoService取消订阅您的演示者。根据PhotoService的实现方式,您可能会发生内存泄漏,因为PhotoService observable具有对presenter的引用,该引用会阻止演示者和PhotoService(具体取决于您的具体实现)被垃圾回收。

编辑:Mosby定义了View的协议。查看项目网站上的入门部分。 HelloWorldView定义了两种方法:showHello()showGoodbye()(由HelloWorldActivity实现)和HelloWorldPresenter调用这两种方法来操作View。 HelloWorldPresenter也会取消异步请求以避免内存泄漏。你也应该这样做。否则,您的演示者只能在改装httpcall完成后进行垃圾收集。