Android MVP MVVM浅谈

来源:互联网 发布:js涂料防水施工工艺 编辑:程序博客网 时间:2024/05/16 09:53
  • 关于MVC、MVP、MVVM认识及介绍,请详细阅读并深入了解
    https://juejin.im/entry/56ebb4ad5bbb50004c440972

  • 关于MVC、MVP、MVVM的理解无外乎对数据的处理方式进一步的进行优化
    这里写图片描述

  • MVP P层实现Modle层获取数据,初始化Model,View层接口实现接口方法进行数据更新,数据加载,弹窗以及提示,而Activity仍然要实现View层接口在activity中对数据进行展示,相对于MVC而言是简化了很多,但是在Activity中仍然代码臃肿,需要处理很多数据展示等操作,下面是MVP P层以及Activity中代码。

  • `public class MoviePresenter implements MovieContract.IMoviePresenter {
    MovieContract.IMovieModel mIMovieModel;//M层
    MovieContract.IMovieView mIMovieView;//V层
    public int start = 0;//从第几个开始
    public int count = 4;//请求多少个

`

  List<Movies.SubjectsBean> mMovies = new ArrayList<>();//请求到的电影信息对象集合    public MoviePresenter(MovieContract.IMovieView mIMovieView) {        this.mIMovieView = mIMovieView;        mIMovieModel = new MovieModel();    }
@Override    public void getMovie() {        mIMovieView.showProgress();//通知V层显示对话框        //每次刷新加载4个        mIMovieModel.getMovie(start, count, new OnHttpCallBack<Movies>() {//有一个请求结果的回调,即我调用请求电影信息的方法了,M层要返回一个成功还是失败的信息给我            @Override            public void onSuccessful(Movies movies) {//获取电影信息成功了,返回movies对象                mIMovieView.hideProgress();//通知V层隐藏对话框                mMovies.addAll(movies.getSubjects());//追加数据                mIMovieView.showData(mMovies);//将获取到的信息显示到界面之前                mIMovieView.showBottom(start - 5);//实现换页效果            }            @Override            public void onFaild(String errorMsg) {                mIMovieView.hideProgress();//通知V层隐藏对话框                mIMovieView.showInfo(errorMsg);//通知V层显示错误信息            }        });        start = start + 4;//改变请求的起点    }    /**     * 加载更多     */    @Override    public void loadMoreMovie() {        getMovie();    }
**Activity端代码**public class MovieActivity extends BaseActivity implements MovieContract.IMovieView {    MoviePresenter mMoviePresenter;    private ProgressDialog mProgressDialog;    @InjectView(R.id.rv_movie_list)    RecyclerView rvMovieList;    @InjectView(R.id.store_house_ptr_frame)    PtrFrameLayout storeHousePtrFrame;    private TextView load_more;//加载更多的按钮    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        initView();        mMoviePresenter = new MoviePresenter(this);        mMoviePresenter.getMovie();//启动软件时默认加载    }    @Override    protected void $setToolBar() {        super.$setToolBar();        setTitle("豆瓣Top250的电影");        setLeftImage(R.drawable.back);        setRightTitle("电影");    }    /**     * 初始化布局     */    private void initView() {        setContentView(R.layout.content_movie);        ButterKnife.inject(this);        $setToolBar();        initPtr();        rvMovieList.setLayoutManager(new LinearLayoutManager(mActivity));//设置为listview的布局        rvMovieList.setItemAnimator(new DefaultItemAnimator());//设置动画        rvMovieList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));//添加分割线    }    /**     * 初始化(配置)下拉刷新组件     */    private void initPtr() {        //下面是一些基础的配置,直接拿来用就可以 不用深究        storeHousePtrFrame.setResistance(1.7f);        storeHousePtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);        storeHousePtrFrame.setDurationToClose(200);        storeHousePtrFrame.setDurationToCloseHeader(1000);        storeHousePtrFrame.setPullToRefresh(false);        storeHousePtrFrame.setKeepHeaderWhenRefresh(true);        StoreHouseHeader header = new StoreHouseHeader(this);        float scale = getResources().getDisplayMetrics().density;        header.setPadding(0, (int) (15 * scale + 0.5f), 0, (int) (15 * scale + 0.5f));        header.initWithString("GY");//自定义头显示的字样,设置图片的话看另外的api//      header.invalidateDrawable();        header.setTextColor(Color.RED);        header.setBackgroundColor(Color.parseColor("#11000000"));        storeHousePtrFrame.setHeaderView(header);//添加头        storeHousePtrFrame.addPtrUIHandler(header);//同时也要加上这一句        storeHousePtrFrame.setPtrHandler(new PtrHandler() {            @Override            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {                return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);            }            @Override            public void onRefreshBegin(PtrFrameLayout frame) {                mMoviePresenter.loadMoreMovie();//下拉刷新的时候加载更多数据                frame.postDelayed(new Runnable() {                    @Override                    public void run() {                        storeHousePtrFrame.refreshComplete();                    }                }, 150);//为了增加用户体验 延迟0.15s再通知刷新结束            }        });    }    @Override    public void showBottom(int lastIndex) {        load_more.setText("点击加载更多");//设置最底下的加载更多显示的内容    加载中-->点击加载更多        rvMovieList.scrollToPosition(lastIndex);    }    @Override    public Context getCurContext() {        return this;    }    @Override    public void showProgress() {        mProgressDialog = ProgressDialog.show(this, "提示", "正在获取中,请稍后...");    }    @Override    public void hideProgress() {        mProgressDialog.hide();    }    /**     * 显示数据     *     * @param movies     */    @Override    public void showData(List<Movies.SubjectsBean> movies) {        //鸿洋大神的通用适配器(真的很好用哦)        CommonAdapter<Movies.SubjectsBean> commonAdapter = new CommonAdapter<Movies.SubjectsBean>(this, R.layout.movie_item, movies) {            @Override            protected void convert(ViewHolder holder, Movies.SubjectsBean subjectsBean, int position) {                String title = (position + 1) + "、" + subjectsBean.getTitle() + "/" + subjectsBean.getOriginal_title();                holder.setText(R.id.tv_movie_title, title);//设置电影名                String doc = "";                for (Movies.SubjectsBean.DirectorsBean directorsBean : subjectsBean.getDirectors()) {                    doc += directorsBean.getName() + "  ";                }                holder.setText(R.id.tv_movie_doc, "导演:" + doc);                String casts = "";                for (Movies.SubjectsBean.CastsBean castsBean : subjectsBean.getCasts()) {                    casts += castsBean.getName() + "  ";                }                holder.setText(R.id.tv_movie_art, "主演:" + casts);                String genres = "";                for (String genre : subjectsBean.getGenres()) {                    genres += genre + " ";                }                holder.setText(R.id.tv_movie_type, subjectsBean.getYear() + " / " + genres);//年份+分级                holder.setText(R.id.tv_movie_grade, subjectsBean.getRating().getAverage() + "");//评分                ImageView iv_pic = holder.getView(R.id.iv_movie_pic);                Glide.with(mActivity)                        .load(subjectsBean.getImages().getSmall())                        .diskCacheStrategy(DiskCacheStrategy.ALL)//加快显示速度---缓存在本地磁盘                        .into(iv_pic);//图片            }        };        /**         * 配置加载更多(通用适配器里面的类哦)         */        LoadMoreWrapper mLoadMoreWrapper = new LoadMoreWrapper(commonAdapter);//加载更多的包装器(传入通用适配器)        View view = View.inflate(mActivity, R.layout.load_more, null);        //要设置一下的布局参数,因为布局填充到包装器的时候,自己的一些属性会无效        LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);        view.setLayoutParams(mLayoutParams);        load_more = (TextView) view.findViewById(R.id.tv_load_more);        //监听点击加载更多事件        load_more.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                load_more.setText("加载中...");//点击加载更多-->加载中                mMoviePresenter.loadMoreMovie();            }        });        mLoadMoreWrapper.setLoadMoreView(view);        rvMovieList.setAdapter(mLoadMoreWrapper);//注意  这里添加的是包装器 不是适配器哦    }    @Override    public void showInfo(String info) {        ToastUtils.showToast(this, info);    }
  • MVVM VM层实现数据请求监听器,初始化Modle实现类,调用获取数据的方法拿到数据,在成功失败的回调方法里面对数据进行提示,刷新,加载,对UI进行数据展示,前提是你引入DataBinding引入布局,不知道的可以先去查一下MVVM引入DataBinding如何进行实现的。下面是VM以及activity代码。
  • public class MovieListVm implements OnHttpCallBack<Movies>{
    public int start = 0;//从第几个开始
    public int count = 4;//请求多少个
    MovieModleBiz movieModleBiz;
 private TextView load_more;//加载更多的按钮    List<Movies.SubjectsBean> mMovies = new ArrayList<>();//请求到的电影信息对象集合    private ActivityMovieBinding binding;    private Context context;    MovieAdapter movieAdapter;    private MovieListVm movieListVm;    private ProgressDialog mProgressDialog;    public MovieListVm(Context context,ActivityMovieBinding binding){        this.binding=binding;        this.context=context;        init();    }    /**     * 初始化     */    private void init() {        movieModleBiz = new MovieModleBiz();        firstLoadData();    }    /**     * 首次加载     */    public void firstLoadData() {         showProgress();//通知V层显示对话框          movieModleBiz.getMovie(start, count,this);          start = start + 4;//改变请求的起点    }    @Override    public void onSuccessful(Movies movies) {        hideProgress();//通知V层隐藏对话框        mMovies.addAll(movies.getSubjects());//追加数据        movieAdapter=new MovieAdapter(context,R.layout.movie_item,mMovies);       showData(mMovies);//将获取到的信息显示到界面之前       showBottom(start - 5);//实现换页效果    }    @Override    public void onFaild(String errorMsg) {        hideProgress();//通知V层隐藏对话框        showInfo(errorMsg);//通知V层显示错误信息    }   public void showBottom(int lastIndex){       binding.rvMovieList.scrollToPosition(lastIndex);   };    public void showProgress(){        mProgressDialog = ProgressDialog.show(context, "提示", "正在获取中,请稍后...");    };//显示进度条    public void hideProgress(){            mProgressDialog.hide();    };//隐藏进度条    public  void showData(List<Movies.SubjectsBean> movies){        LoadMoreWrapper mLoadMoreWrapper = new LoadMoreWrapper(movieAdapter);//加载更多的包装器(传入通用适配器)        View view = View.inflate(context, R.layout.load_more, null);        //要设置一下的布局参数,因为布局填充到包装器的时候,自己的一些属性会无效        LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);        view.setLayoutParams(mLayoutParams);        load_more = (TextView) view.findViewById(R.id.tv_load_more);        //监听点击加载更多事件        load_more.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                load_more.setText("加载中...");//点击加载更多-->加载中                firstLoadData();            }        });        mLoadMoreWrapper.setLoadMoreView(view);       binding. rvMovieList.setAdapter(mLoadMoreWrapper);//注意  这里添加的是包装器 不是适配器哦    };//显示数据到View上    public void showInfo(String info){        ToastUtils.showToast(context, info);    };//提示用户,提升友好交互}
**Acitivity代码**public class MvvmMoviActivity extends BaseMvVmActivity<ActivityMovieBinding>{    RecyclerView rvMovieList;    PtrFrameLayout storeHousePtrFrame;    private MovieListVm moviewListVm;    @Override    public int getLayoutId() {        return R.layout.activity_movie;    }    @Override    public void init(Bundle savedInstanceState) {        initView();        initVm();    }    private void initVm() {      moviewListVm= new MovieListVm(this, viewDataBinding);    }    private void initView() {        rvMovieList=viewDataBinding.rvMovieList;        storeHousePtrFrame=viewDataBinding.storeHousePtrFrame;        initPtr();        rvMovieList.setLayoutManager(new LinearLayoutManager(this));//设置为listview的布局        rvMovieList.setItemAnimator(new DefaultItemAnimator());//设置动画        rvMovieList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));//添加分割线    }    /**     * 初始化(配置)下拉刷新组件     */    private void initPtr() {        //下面是一些基础的配置,直接拿来用就可以 不用深究        storeHousePtrFrame.setResistance(1.7f);        storeHousePtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);        storeHousePtrFrame.setDurationToClose(200);        storeHousePtrFrame.setDurationToCloseHeader(1000);        storeHousePtrFrame.setPullToRefresh(false);        storeHousePtrFrame.setKeepHeaderWhenRefresh(true);        StoreHouseHeader header = new StoreHouseHeader(this);        float scale = getResources().getDisplayMetrics().density;        header.setPadding(0, (int) (15 * scale + 0.5f), 0, (int) (15 * scale + 0.5f));        header.initWithString("GY");//自定义头显示的字样,设置图片的话看另外的api//      header.invalidateDrawable();        header.setTextColor(Color.RED);        header.setBackgroundColor(Color.parseColor("#11000000"));        storeHousePtrFrame.setHeaderView(header);//添加头        storeHousePtrFrame.addPtrUIHandler(header);//同时也要加上这一句        storeHousePtrFrame.setPtrHandler(new PtrHandler() {            @Override            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {                return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);            }            @Override            public void onRefreshBegin(PtrFrameLayout frame) {               //下拉刷新的时候加载更多数据                moviewListVm.firstLoadData();                frame.postDelayed(new Runnable() {                    @Override                    public void run() {                        storeHousePtrFrame.refreshComplete();                    }                }, 150);//为了增加用户体验 延迟0.15s再通知刷新结束            }        });    }}
  • 下面是在github上的源码,在了解了MVP和MVVM之后可以下载源码进行验证实现。
  • github链接