mvp模式初识

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

  1. 第一步建立相关的基类接口分别是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解除绑定,防止内存泄露
    }
  1. 然后建立一个联系接口类将你要扩展的继承接口全部统一起来,再写两个类实现其对应的方法
//假如这是我要写的新闻页面
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) {



这是我参照AndroidFire,一款新闻阅读 App,基于 Material Design + MVP + RxJava + Retrofit + Glide,基本涵盖了当前 Android 端开发最常用的主流框架,基于此框架可以快速开发一个 app理解的。

转载于:https://my.oschina.net/u/3292760/blog/844638

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值