他在论文中提到 we refer to this kind(指应用程序全局且使用interactor, command以及selection概念的) of controller as a presenter, 所以 Presenter 也是一种 Controller. MVC 和 MVP 的依赖关系图是一样的.
Android 中的 MVP
Android 中的 MVP, Presenter 作为桥梁的功能更加明显, 但是也有一些变种类型, 比如 Google 的 MVP 模式, 添加了 Contract 作为合约类, 定义了 View 和 Presenter 之间的接口, 而 Model 则作为数据中心, 提供所有获取数据的接口, Prsenter 中只需要选择是使用测试的 Data Repo 还是 正式的 Data Repo 即可.
许多年前我的显示器上就贴着一段引用自 Scott Meyers 所写的 Effective C++ 中的一段话:
Anytime you find yourself writing code of the form “if the object is of type T1, then do something, but if it’s of type T2, then do something else,” slap yourself.
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.mContext = activity;
}
@Override
public Context getContext() {
if (super.getContext() != null) {
return super.getContext();
}
return mContext;
}
然后尽量调用getContext()方法.
因为getActivity()方法不能重写,所以只好加上判断:
if(isAdded()) {
//XXXX
}
如果使用 ViewPager + Fragment, ViewPager 在初始化时会缓存多个 Fragment, 这里可以通过 setUserVisibleHint 来判断 Fragment 是否可见.一个简单封装的 Fragment 如下:
public abstract class BaseFragment extends Fragment {
//必须有空的构造函数
public BaseFragment() {
}
//避免ViewPager在一开始创建
private boolean hasLazyLoad = false;
public void setHasLazyLoad(boolean hasLazyLoad) {
this.hasLazyLoad = hasLazyLoad;
}
/**
* 懒加载,防止ViewPager重复创建
*/
protected void onLazyLoad() {
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint() && !hasLazyLoad) {
onLazyLoad();
hasLazyLoad = true;
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
hasLazyLoad = false;
}
}
注意需要在 onDestroyView()中复位标志位,因为 ViewPager 的切换会导致 Fragment 的销毁.
在 Fragment 中嵌套 Fragment 时, 最好使用 getChildFragmentManager() 来获取 FragmentManager 示例,同时在 Fragment 销毁时, 利用反射将其置为空. 否则会导致错误 java.lang.IllegalStateException: Activity has been destroyed :
@Override
public void onDestroyView() {
super.onDestroyView();
//解决嵌套 Fragment 的bug
try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}