MVP框架實例解析

關於MVC,MVP,MVVM,有很多人寫了區別,比如這篇

這裏只是分析大多數人使用的MVP框架 mosby MVP代碼請點擊

首先再來回顧一下MVP的整體概念,View不直接和Model打交道(區別於MVC)View和Presenter之間互相調用,Model只和Presenter交互,一般由Presenter這方調用。



mosby MVP框架代碼相關幾個部分

View層:

  •  MvpActivity(實際控制)
  •  MvpView (接口)
  •  ActivityMvpDelegateImpl (用於處理Presenter的新建)

Presenter層

  • MvpPresenter
  • MVpBasePresenter


部分重要代碼 

MvpView.java是空接口爲的是外部使用View接口

MvpActivity.java 

public abstract class MvpActivity<V extends MvpView, P extends MvpPresenter<V>>
    extends AppCompatActivity implements MvpView,
    com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback<V,P> {

  protected ActivityMvpDelegate mvpDelegate;
  protected P presenter;
  protected boolean retainInstance;

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getMvpDelegate().onCreate(savedInstanceState);
  }
  @NonNull protected ActivityMvpDelegate<V, P> getMvpDelegate() {
    if (mvpDelegate == null) {
      mvpDelegate = new ActivityMvpDelegateImpl(this, this, true);
    }

    return mvpDelegate;
  }

  @NonNull @Override public P getPresenter() {
    return presenter;
  }

  @Override public void setPresenter(@NonNull P presenter) {
    this.presenter = presenter;
  }

  @NonNull @Override public V getMvpView() {
    return (V) this;
  }
}

MvpActivity這裏作爲 ActivityMvpDelegateImpl的Callbcack設置Presenter和View(Activity本身)。MvpActivity裏面存有Presenter的實例,則可以通過調用getPresenter實現View到Presenter的調用。


ActivityMvpDelegateImpl.java

@Override public void onCreate(Bundle bundle) {

  P presenter = null;

  if (bundle != null && keepPresenterInstance) {

    mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);

    if (DEBUG) {
      Log.d(DEBUG_TAG,
          "MosbyView ID = " + mosbyViewId + " for MvpView: " + delegateCallback.getMvpView());
    }

    if (mosbyViewId != null
        && (presenter = PresenterManager.getPresenter(activity, mosbyViewId)) != null) {
      //
      // Presenter restored from cache
      //
      if (DEBUG) {
        Log.d(DEBUG_TAG,
            "Reused presenter " + presenter + " for view " + delegateCallback.getMvpView());
      }
    } else {
      //
      // No presenter found in cache, most likely caused by process death
      //
      presenter = createViewIdAndCreatePresenter();
      if (DEBUG) {
        Log.d(DEBUG_TAG, "No presenter found although view Id was here: "
            + mosbyViewId
            + ". Most likely this was caused by a process death. New Presenter created"
            + presenter
            + " for view "
            + getMvpView());
      }
    }
  } else {
    //
    // Activity starting first time, so create a new presenter
    //
    presenter = createViewIdAndCreatePresenter();
    if (DEBUG) {
      Log.d(DEBUG_TAG, "New presenter " + presenter + " for view " + getMvpView());
    }
  }

  if (presenter == null) {
    throw new IllegalStateException(
        "Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");
  }

  delegateCallback.setPresenter(presenter);
  getPresenter().attachView(getMvpView());

  if (DEBUG) {
    Log.d(DEBUG_TAG, "View" + getMvpView() + " attached to Presenter " + presenter);
  }
}
private P createViewIdAndCreatePresenter() {

  P presenter = delegateCallback.createPresenter();
  if (presenter == null) {
    throw new NullPointerException(
        "Presenter returned from createPresenter() is null. Activity is " + activity);
  }
  if (keepPresenterInstance) {
    mosbyViewId = UUID.randomUUID().toString();
    PresenterManager.putPresenter(activity, mosbyViewId, presenter);
  }
  return presenter;
}

MvpPresenter實例是在MvpActivity的代理ActivityMvpDelegateImpl中創建。並且將當前的View(即Activity實例)設置到了MvpPresenter裏面用於回調。

MvpActivity與MvpPresenter與ActivityMvpDelegateImpl都是1:1:1的關係。


MvpBasePresenter.java

public interface ViewAction<V> {

  /**
   * This method will be invoked to run the action. Implement this method to interact with the view.
   * @param view The reference to the view. Not null.
   */
  void run(@NonNull V view);
}

private WeakReference<V> viewRef;
private boolean presenterDestroyed = false;

@UiThread @Override public void attachView(V view) {
  viewRef = new WeakReference<V>(view);
  presenterDestroyed = false;
}
protected final void ifViewAttached(boolean exceptionIfViewNotAttached, ViewAction<V> action) {
  final V view = viewRef == null ? null : viewRef.get();
  if (view != null) {
    action.run(view);
  } else if (exceptionIfViewNotAttached) {
    throw new IllegalStateException(
        "No View attached to Presenter. Presenter destroyed = " + presenterDestroyed);
  }
通過判斷是否存在View是否存在來執行ViewAction的run方法來執行presenter到View的回調


MVP框架啓動Presenter生成和設置的序列圖



繼承MVP框架自己的實現

MyPresenter.java

public void getData(String data) {
    try {
        Thread.sleep(1000);
    } catch (Exception e){

    }

    ifViewAttached(new ViewAction<MyView>() {
        @Override
        public void run(@NonNull MyView view) {
            view.showData();
        }
    });
} 

MyActivity.java

@NonNull
@Override
public MyPresenter createPresenter() {
    return new MyPresenter();
}
public void getData(View view){
    getPresenter().getData("data");
}
@Override
public void showData(Contributor contributor) {
    topContributor.setText(contributor.toString());
    dismissProgress();
}

View中調用Presenter向Model獲取數據,然後Presenter再回調View(Acitivity)的ShowData方法。



另該MVP框架中使用到的模式有:

  • 代理模式Delegate
  • 泛型和模板設計模式

 等。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章