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
  • 泛型和模板设计模式

 等。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值