Github地址
使用手册 :
Model-View-Presenter library for android
model:获取数据模型
view:视图、数据展示
Presenter:持有view和model的引用,从model获取数据模型,通知view去更新视图
这是一个内部使用代理和组合实现的库,不是一个框架,没有框架的限制。
去掉所有三方库,三方库的维护和升级都会带来问题。
总结:
Activity持有presenter的引用
Presenter持有MvpView的引用
- Activity在onCreate()、onDestroy()
- Fragment在onViewCreated()、onDestroyView()
- View在onAttachedToWindow()、onDetachedFromWindow()
presenter.attachView(getMvpView()); //presenter通过弱引用持有view的引用
presenter.detachView(); //presenter移除view的引用
mosby源码介绍
dependencies {
compile 'com.hannesdorfmann.mosby3:mvp-lce:3.1.0'
compile 'com.hannesdorfmann.mosby3:mvp-nullobject-presenter:3.1.0'
}
MvpLceActivity 相对于MvpActivity,多了一个loadingView、
//CV contentView、M setData()中的数据模型,V view interface, P presenter
public abstract class MvpLceActivity<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>>
extends MvpActivity<V, P> implements MvpLceView<M> {
protected View loadingView;
protected CV contentView;
protected TextView errorView;
//当Activity的布局改动时,即setContentView()或者addContentView()方法执行完毕时就会调用该方法
@CallSuper @Override public void onContentChanged() {
super.onContentChanged();
//createView 都是通过findViewById()来实现的,所以继承自MvpLceActivity的layoutResId都要包含这几个resId
loadingView = createLoadingView(); // findViewById(R.id.loadingView);
contentView = createContentView(); // (CV) findViewById(R.id.contentView);
errorView = createErrorView(); // (TextView) findViewById(R.id.errorView);
//省略判断,loadingView、contentView、errorView都不能为空,且为errorView注册监听事件
}
// errorView的监听事件
protected void onErrorViewClicked() {
loadData(false);
}
//pullToRefresh 为true,由refreshLayout进行加载动画(下拉刷新,上拉加载),false,由自己处理
@Override public void showLoading(boolean pullToRefresh) {
if (!pullToRefresh) {
animateLoadingViewIn();
}
}
//子类重写,可以自定义错误提示文本
protected abstract String getErrorMessage(Throwable e, boolean pullToRefresh);
protected void showLightError(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override public void showError(Throwable e, boolean pullToRefresh) {
String errorMsg = getErrorMessage(e, pullToRefresh);
if (pullToRefresh) { //如果是refreshLayout产生的下拉刷新和上拉加载,则直接toast
showLightError(errorMsg);
} else { //否则展示错误layout
errorView.setText(errorMsg);
animateErrorViewIn();
}
}
// 展示loading
protected void animateLoadingViewIn() {
LceAnimator.showLoading(loadingView, contentView, errorView);
}
// 展示content
@Override public void showContent() {
LceAnimator.showContent(loadingView, contentView, errorView);
}
// 展示errorView
protected void animateErrorViewIn() {
LceAnimator.showErrorView(loadingView, contentView, errorView);
}
}
MvpActivity
使用代理
//V view interface, P presenter
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; //提供get、set操作
protected boolean retainInstance;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMvpDelegate().onCreate(savedInstanceState);
}
@Override protected void onDestroy() {
super.onDestroy();
getMvpDelegate().onDestroy();
}
@NonNull public abstract P createPresenter(); //创建presenter
@NonNull protected ActivityMvpDelegate<V, P> getMvpDelegate() {
if (mvpDelegate == null) {
mvpDelegate = new ActivityMvpDelegateImpl(this, this, true); //创建代理类
}
return mvpDelegate;
}
@NonNull @Override public V getMvpView() {
return (V) this; //得到activity的引用转为viewInterface
}
}
MvpLceView,通用的用于MvpLceActivity。
MvpView 是一个空接口
public interface MvpLceView<M> extends MvpView {
@UiThread
void showLoading(boolean pullToRefresh); //耗时操作展示loading
@UiThread
void showContent(); //请求正确展示内容
@UiThread
void showError(Throwable e, boolean pullToRefresh); //请求错误的回调
@UiThread
void setData(M data); 设置数据源,一般和showContent一起使用
@UiThread
void loadData(boolean pullToRefresh); //加载数据
}
ActivityMvpDelegateImpl 代理实现类
public class ActivityMvpDelegateImpl<V extends MvpView, P extends MvpPresenter<V>>
implements ActivityMvpDelegate {
protected static final String KEY_MOSBY_VIEW_ID = "com.hannesdorfmann.mosby3.activity.mvp.id";
private MvpDelegateCallback<V, P> delegateCallback;
protected boolean keepPresenterInstance;
protected Activity activity;
protected String mosbyViewId = null;
public ActivityMvpDelegateImpl(@NonNull Activity activity,
@NonNull MvpDelegateCallback<V, P> delegateCallback, boolean keepPresenterInstance) {
// 空判断
this.delegateCallback = delegateCallback;
this.activity = activity;
this.keepPresenterInstance = keepPresenterInstance;
}
static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity) {
return keepPresenterInstance && (activity.isChangingConfigurations()
|| !activity.isFinishing());
}
private P createViewIdAndCreatePresenter() {
P presenter = delegateCallback.createPresenter(); //获取presenter
if (keepPresenterInstance) { //做缓存,下次直接从缓存取
mosbyViewId = UUID.randomUUID().toString();
PresenterManager.putPresenter(activity, mosbyViewId, presenter);
}
return presenter;
}
@Override public void onCreate(Bundle bundle) {
P presenter = null;
if (bundle != null && keepPresenterInstance) {
mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);
if (mosbyViewId != null
&& (presenter = PresenterManager.getPresenter(activity, mosbyViewId)) != null) {
//如果缓存里有,则直接从缓存中获取
} else {
//没有缓存,直接创建,most likely caused by process death
presenter = createViewIdAndCreatePresenter();
}
} else {
//activity第一次启动时,直接创建
presenter = createViewIdAndCreatePresenter();
}
delegateCallback.setPresenter(presenter); //给代理设置缓存
getPresenter().attachView(getMvpView()); //presenter持有view的引用
}
//通过接口引用获取presenter
private P getPresenter() {
P presenter = delegateCallback.getPresenter();
return presenter;
}
//通过接口引用获取view
private V getMvpView() {
V view = delegateCallback.getMvpView();
return view;
}
@Override public void onDestroy() {
boolean retainPresenterInstance = retainPresenterInstance(keepPresenterInstance, activity);
getPresenter().detachView(); //presenter移除view的引用
if (!retainPresenterInstance){
getPresenter().destroy();
}
if (!retainPresenterInstance && mosbyViewId != null) {
PresenterManager.remove(activity, mosbyViewId);
}
}
}
MvpPresenter
public interface MvpPresenter<V extends MvpView> {
@UiThread
void attachView(@NonNull V view); //添加view的引用
@UiThread
void detachView(); //移除view的引用
@UiThread
void destroy();
}
MvpBasePresenter
public class MvpBasePresenter<V extends MvpView> implements MvpPresenter<V> {
public interface ViewAction<V> {
void run(@NonNull V view);
}
private WeakReference<V> viewRef; //弱引用
private boolean presenterDestroyed = false;
//添加view的引用
@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);
}
}
//如果viewAttached,执行viewAction
protected final void ifViewAttached(ViewAction<V> action) {
ifViewAttached(false, action);
}
//移除view的引用
@Override public void detachView() {
if (viewRef != null) {
viewRef.clear();
viewRef = null;
}
}
}