簡體   English   中英

我的MVP實施模式有效嗎?

[英]Is my implementation pattern for MVP valid?

我是Android和MVP的新手,在過去的1.5年中我一直在進行iOS編程,因此我發現易於理解的委托模式。 我已經以視圖符合演示者協議的方式實現了MVP,這使演示者可以忽略視圖的特定類型,但可以知道某些方法是給定的,因此可以調用“視圖”。 我一直在閱讀各種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而言,我似乎找不到推薦我正在做什么的資源,而且我有足夠的自我懷疑,我想我會問我的第一個StackOverflow問題。 擁有MVP經驗的人可以對此有所了解嗎?

另外,如果我在錯誤的位置提問,請隨時將我指向正確的位置以發布此內容。

謝謝 :)

從我的角度來看,您正在做與Mosby相同的事情。 唯一的區別是接口(或Objective-C中的協議)世界的名稱。 您將其稱為PresenterProtocol而Mosby將其MvpView 兩者都在完成相同的工作:向Presenter提供Presenter者可以調用以操縱視圖的方法的Api。

唯一沒有意義的是使用方法viewDoesConform() 在Java中,您具有類型安全性。 您可以使用Presenter的泛型類型V來確保您的片段正在實現Presenter的協議。 只需將其更改為V extends BasePresentersProtocol

此外,我認為擁有演示者的“共享實例”(也稱為Singleton模式)是沒有意義的。 我認為擁有PhotoService的“共享實例”會更有意義。 但是,但也請注意,這樣做將使您的代碼不再可測試(單元測試)。 您應該通過google進行依賴注入或控制逆,以了解如何編寫模塊化,可重用和可測試的代碼。 我不是在談論像Dagger,spring或guice這樣的依賴注入框架。 您只應該了解依賴注入背后的想法。 您可以完全遵循此原理編寫類,而無需依賴注入框架(即使用構造函數參數)。

旁注:您永遠不會從PhotoService退訂演示者。 根據PhotoService的實現方式,您可能會發生內存泄漏,因為Observable的PhotoService具有對演示者的引用,該引用可防止演示者和PhotoService(取決於您的具體實現)被垃圾回收。

編輯:Mosby定義了View的協議。 查看項目網站上的入門部分。 HelloWorldView定義了兩個方法: showHello()showGoodbye() (由HelloWorldActivity ),並且HelloWorldPresenter調用這兩個方法來操縱View。 HelloWorldPresenter還會取消異步請求,以避免內存泄漏。 您也應該這樣做。 否則,只有在改造httpcall完成后才能對您的演示者進行垃圾回收。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM