MVP模式入门

    |     2016年9月1日   |   Android经验   |     0 条评论   |    1996

概述

应用软件程序开发过程中,大都会涉及到UI界面、数据、业务逻辑处理。当业务逻辑非常复杂的时候为了能更清晰的开发维护程序代码,需要对程序进行框架设计,最早的MVC模式便应运而生.后来也被应用于Android应用程序开发中。

MVP可以看作是MVC的一种升级。在MVC中Activity其实是View层级,但是通常在使用中Activity即是View也是Controller,并没有将View层和Controller层进行分离,耦合度非常高,非常不利于项目的管理。这时候MVP就应运而生了。

MVC架构

M : 业务层和模型层,相当与javabean和我们的业务请求代码
   model层主要负责:
   · 从网络,数据库,文件,传感器,第三方等数据源读写数据。
   · 对外部的数据类型进行解析转换为APP内部数据交由上层处理。
   · 对数据的临时存储,管理,协调上层数据请求。

 V : 视图层,对应Android的layout.xml布局文件
 C : 控制层,对应于Activity中对于UI 的各种操作

看起来MVC架构很清晰,但是实际的开发中,请求的业务代码往往被丢到了Activity里面,大家都知道layout.xml的布局文件只能提供默认的UI设置,所以开发中视图层的变化也被丢到了Activity里面,再加上Activity本身承担着控制层的责任。所以Activity达成了MVC集合的成就,最终我们的Activity就变得越来越难看,从几百行变成了几千行。维护的成本也越来越高

新的MVP架构

M : 还是业务层和模型层
V : 视图层的责任由Activity来担当
P : 新成员Prensenter 用来代理 C(control) 控制层,是View和Model的中间“桥梁”,负责View和Model间的交互

MVP与MVC最大的不同,其实是Activity职责的变化,由原来的C (控制层) 变成了 V(视图层),不再管控制层的问题,只管如何去显示。控制层的角色就由我们的新人 Presenter来担当,这种架构就解决了Activity过度耦合控制层和视图层的问题。

mvp

 

 

实例

用MVP模式实现下图效果
cheap

第一步View层

/**
 * 定义UI视图逻辑
 */
public interface ICheapView {
    void setListViewAdapter(ReadNewsAdapter adpater);
    void showToastMessage(String message);
    void setBannerLayoutData(List<AdsBean> list);
}

public class CheapFragment extends BaseMvpFragment<ICheapView, CheapPresenter> implements ICheapView, View.OnClickListener {
    private EditText mSearchKey;
    private ListView mListView;
    private FrameLayout mListHeadView;
    private BannerLayout mBannerLayout;

    public static CheapFragment newInstance() {
        CheapFragment fragment = new CheapFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mListHeadView = (FrameLayout) inflater.inflate(fragment_cheap_banner_layout, null);
        return inflater.inflate(R.layout.fragment_cheap_layout, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mSearchKey = (EditText) getView().findViewById(R.id.com_search_edit);
        mBannerLayout = (BannerLayout) mListHeadView.findViewById(R.id.banner);
        mListView = (ListView) getView().findViewById(R.id.cheap_listview);
        mListView.addHeaderView(mListHeadView);
        mSearchKey.setOnClickListener(this);

        mPresenter.setListViewAdapter();
        mPresenter.setListBannerViewData();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.com_search_edit:
                getActivity().onSearchRequested();
                break;
        }
    }

    @Override
    public CheapPresenter initPresenter() {
        return new CheapPresenter(getActivity());
    }

    @Override
    public void setListViewAdapter(ReadNewsAdapter adpater) {
        mListView.setAdapter(adpater);
    }

    @Override
    public void showToastMessage(String message) {
        Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setBannerLayoutData(List<AdsBean> urls) {
        List<String> list = new ArrayList<>();
        for (AdsBean ads : urls) {
            list.add(ads.getImgsrc());
        }
        mBannerLayout.setViewUrls(list);
        //添加监听事件
        mBannerLayout.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
            @Override
            public void onItemClick(int position) {
                showToastMessage(String.valueOf(position));
            }
        });
    }
}

第二步Presenter层

/**
 * 定义业务逻辑
 */
public interface ICheapPresenter {
    void setListViewAdapter();
    void setListBannerViewData();
}

public class CheapPresenter extends BasePresenter<ICheapView> implements ICheapPresenter{
    private ICheapModel mCheapModel;
    private ReadNewsAdapter mReadNewsAdapter;

    public CheapPresenter(Context context) {
        mCheapModel = new CheapModel();
        mReadNewsAdapter = new ReadNewsAdapter(context);
    }

    @Override
    public void setListViewAdapter() {
        mView.setListViewAdapter(mReadNewsAdapter);
    }

    @Override
    public void setListBannerViewData() {
        mCheapModel.setListAndAdsData(new CallbackListener<NewsTextBean>() {
            @Override
            public void onSuccess(NewsTextBean data) {
                List<NewsTextItemBean> newsTextItemBeanList = data.getT1348647909107();
                mReadNewsAdapter.addDatas(0,newsTextItemBeanList);
                List<AdsBean> adsLists = newsTextItemBeanList.get(0).getAds();
                mView.setBannerLayoutData(adsLists);
            }

            @Override
            public void onFailure(String message) {
                mView.showToastMessage(message);
            }
        });
    }
}

第三步实现Mode层

public interface ICheapModel {
    void setListAndAdsData(final CallbackListener<NewsTextBean> listener);
}

public class CheapModel implements ICheapModel {
    @Override
    public void setListAndAdsData(final CallbackListener<NewsTextBean> listener) {
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl("http://c.m.163.com/")
                .build();

        RetrofitCall call = retrofit.create(RetrofitCall.class);
        Call<NewsTextBean> mCall = call.getNewsText();
        mCall.enqueue(new Callback<NewsTextBean>() {
            @Override
            public void onResponse(Call<NewsTextBean> call, Response<NewsTextBean> response) {
                NewsTextBean newsTextBean =  response.body();
                listener.onSuccess(newsTextBean);
            }

            @Override
            public void onFailure(Call<NewsTextBean> call, Throwable t) {
                listener.onFailure(t.getMessage());

            }
        });
    }
}

BaseMvpFragment主要封装对Presenter的实例化.
BasePresenter实现在Presenter中持有View的引用.

public abstract class BasePresenter<T> {
    /*这个基类的Presenter 主要的作用就是将当前Presenter持有的view 在合适的时候给清除掉*/
    public T mView;

    public void attach(T mView) {
        this.mView = mView;
    }

    public void dettach() {
        mView = null;
    }

}
public abstract class BaseMvpFragment<V, T extends BasePresenter<V>> extends Fragment {
    /*定义一个Presenter 用于解绑持有的View
       *
       * 在onAttach进行初始化Presenter的操作
       * 在onCreate中进行绑定
       * 在onDestroy 中进行解绑
       *
       **/
    public T mPresenter;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mPresenter = initPresenter();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter.attach((V) this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mPresenter.dettach();
    }

    /* 这里是适配为不同的View 装载不同Presenter*/
    public abstract T initPresenter();
}

参考学习

Android单排上王者系列之Android MVP解析实践

Android mvp 架构的自述

Retrofit+MVP模式学习

 

转载请注明来源:MVP模式入门
回复 取消