mvp模式 : m指model即数据模型,有关操作数据的方法(保存数据,加载数据,联网获取数据等) v指view即视图模型,一般就是activity或者fragment,有关操作视图的方法(显示加载框,显示提示框等) p指presenter即监控者模型,Model与View之间的交互由Presenter完成
两者差异
MVP模式: View不直接与Model交互,而是通过与Presenter交互来与Model间接交互 Presenter与View的交互是通过接口来进行的,更有利于添加单元测试 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑
MVC模式: View可以与Model直接交互 Controller是基于行为的,并且可以被多个View共享 可以负责决定显示哪个View
- 第一步建立相关的基类接口分别是IBaseModel 和 IBaseView 还有抽象类BasePresenter
public interface BaseModel {
//基类model看着来,我感觉不用写什么方法还更好扩展
}
public interface BaseView {
/*******内嵌加载*******/
void showLoading(String title);
void stopLoading();
void showErrorTip(String msg);
}
public abstract class BasePresenter<T,E>{
//基类监控者将view和model联系起来利用setVM方法
public Context mContext;
public E mModel;
public T mView;
public void setVM(T v, E m) {
this.mView = v;
this.mModel = m;
this.onStart();
}
public void onStart(){
};
public void onDestroy() {
//在监控者毁灭后将监控者和view利用eventbus解除绑定,防止内存泄露
}
- 然后建立一个联系接口类将你要扩展的继承接口全部统一起来,再写两个类实现其对应的方法
//假如这是我要写的新闻页面
public interface NewsMainContract {
interface Model extends BaseModel {
//联网获取数据
List<NewsChannelTable> loadnews();
}
interface View extends BaseView {
//显示新闻类表填充到视图中例如将获取的新闻集合传入到listview中
void showNews(List<NewsChannelTable> news);
//视图中改变频道类型
void changeChannel();
}
abstract static class Presenter extends BasePresenter<View, Model> {
/**两者联系的方法,例如view中changeChannel了就要利用这个presenter去调用model的loadnews()
*又有假如loadnews又要通过presenter调用baseview的showLoading(String title)来控制视图显示正在加载
*/
public abstract void lodeMineChannelsRequest();
}
}
public class NewsMainModel implements NewsMainContract.Model {
@Override
public List<NewsChannelTable> loadnews() {
List<NewsChannelTable> data = new ArrayList<NewsChannelTable>();
//具体写联网获取数据的方法,获取以后返回data
retrun data;
}
}
public class NewsMainPresenter extends NewsMainContract.Presenter{
@Override
public void onStart() {
//监听新闻频道变化刷新,一旦新闻频道变化
BasePresenter.mView.changeChannel(){
//就调用model的加载数据方法
List<NewsChannelTable> loadnews();
}
}
@Override
public void lodeMineChannelsRequest() {
//监听model的加载数据方法,一旦加载调用view的显示加载框方法,加载成功后调用view的停止显示加 //载框方法同时调用view的显示数据方法,加载失败调用view的显示错误方法
//监听是否开始加载数据
BasePresenter.mModel.loadnews(){
//就调用view的显示加载框
void showLoading(String title);
//加载完成调用view的停止加载框和显示数据方法,一旦失败就调用showError()方法
void stopLoading();
void showNews(List<NewsChannelTable> news);
}
}
}
public abstract class BaseFragment<T extends BasePresenter, E extends BaseModel> extends Fragment {
protected View rootView;
public T mPresenter;
public E mModel;
public RxManager mRxManager;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (rootView == null)
rootView = inflater.inflate(getLayoutResource(), container, false);
mRxManager=new RxManager();
ButterKnife.bind(this, rootView);
mPresenter = TUtil.getT(this, 0);
mModel= TUtil.getT(this,1);
if(mPresenter!=null){
mPresenter.mContext=this.getActivity();
}
initPresenter();
initView();
return rootView;
}
//获取布局文件
protected abstract int getLayoutResource();
//简单页面无需mvp就不用管此方法即可,完美兼容各种实际场景的变通
public abstract void initPresenter();
//初始化view
protected abstract void initView();
public class TUtil {
public static <T> T getT(Object o, int i) {
try {
return ((Class<T>) ((ParameterizedType) (o.getClass()
.getGenericSuperclass())).getActualTypeArguments()[i])
.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> forName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
public class NewsMainFragment extends BaseFragment<NewsMainPresenter,NewsMainModel>implements NewsMainContract.View {
@Bind(R.id.toolbar)
Toolbar toolbar;
@Bind(R.id.tabs)
TabLayout tabs;
@Bind(R.id.add_channel_iv)
ImageView addChannelIv;
@Bind(R.id.view_pager)
ViewPager viewPager;
@Bind(R.id.fab)
FloatingActionButton fab;
private BaseFragmentAdapter fragmentAdapter;
@Override
protected int getLayoutResource() {
return R.layout.app_bar_news;
}
@Override
public void initPresenter() {
mPresenter.setVM(this,mModel);
}
@Override
public void initView() {
mPresenter.lodeMineChannelsRequest();
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRxManager.post(AppConstant.NEWS_LIST_TO_TOP, "");
}
});
}
@OnClick(R.id.add_channel_iv)
public void clickAdd(){
NewsChannelActivity.startAction(getContext());
}
@Override
public void returnMineNewsChannels(List<NewsChannelTable> newsChannelsMine) {
if(newsChannelsMine!=null) {
List<String> channelNames = new ArrayList<>();
List<Fragment> mNewsFragmentList = new ArrayList<>();
for (int i = 0; i < newsChannelsMine.size(); i++) {
channelNames.add(newsChannelsMine.get(i).getNewsChannelName());
mNewsFragmentList.add(createListFragments(newsChannelsMine.get(i)));
}
if(fragmentAdapter==null) {
fragmentAdapter = new BaseFragmentAdapter(getChildFragmentManager(), mNewsFragmentList, channelNames);
}else{
//刷新fragment
fragmentAdapter.setFragments(getChildFragmentManager(),mNewsFragmentList,channelNames);
}
viewPager.setAdapter(fragmentAdapter);
tabs.setupWithViewPager(viewPager);
MyUtils.dynamicSetTabLayoutMode(tabs);
setPageChangeListener();
}
}
private void setPageChangeListener() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private NewsFrament createListFragments(NewsChannelTable newsChannel) {
NewsFrament fragment = new NewsFrament();
Bundle bundle = new Bundle();
bundle.putString(AppConstant.NEWS_ID, newsChannel.getNewsChannelId());
bundle.putString(AppConstant.NEWS_TYPE, newsChannel.getNewsChannelType());
bundle.putInt(AppConstant.CHANNEL_POSITION, newsChannel.getNewsChannelIndex());
fragment.setArguments(bundle);
return fragment;
}
@Override
public void showLoading(String title) {
}
@Override
public void stopLoading() {
}
@Override
public void showErrorTip(String msg) {