AndroidAndroidandroid开源

Android MVP 实例运用

2016-04-26  本文已影响1185人  晓峰残月

Android MVP介绍

随着技术的发展,Activity(View) 做的事情越来越多,动辄几百上千行的代码使得 Activity 越来越臃肿。为了更好的划分视图(View)和模型(Model)之间的职责,让 View 只处理数据的展示和用户的交互,把数据的处理交由 Model 处理。

在MVP模式里通常包含4个要素:

  1. View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
  2. View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
  3. Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
  4. Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
MVP.png

Android MVP 好处

MVP模式可以让显示界面和数据分离,我们开发的应用可以分离至少三层,这样也可以进行独立测试。更加的好维护(代码复用)数据分离有利于信息的隐蔽等等优点,相比较他的优点,缺点就可以忽略了。

Android MVP 实例

下图是采用MVP做的一个列表页面,实现了刷新,加载更多的功能。

S60426-143923.jpg

目录结构

tree.png

View 层

view 层的接口 用来与Presenter进行交互

public interface MovieView extends MVPView {

    void showLoading();

    void hideLoading();

    void showSwipeRefresh();

    void hideSwipeRefresh();

    boolean isSwipeRefresh();

    void showMovies(List<Movies> movieList);

    void appendMovies(List<Movies> movieList);

    void showToast(String content);

    boolean isTheListEmpty();

}

view 接口的实现类(Activity)

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        // 设置 presenter
        moviePresenter = new MoviePresenter();
        moviePresenter.attachView(this);
        initializeSwipe();
        initializeRecycler();
    }

    /**
     * 初始化SwipeRefreshLayout和设置下拉刷新事件
     * */
    private void initializeSwipe() {
        mainSwipe.setColorSchemeResources(
                android.R.color.holo_blue_light,
                android.R.color.holo_red_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_green_light);
        mainSwipe.setSize(SwipeRefreshLayout.LARGE);
        mainSwipe.setProgressViewEndTarget(true, 200);
        mainSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                moviePresenter.refresh();
            }
        });
    }

    /**
     * 初始化RecyclerView
     * */
    private void initializeRecycler() {
        mainRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
        adaper = new MovieAdaper();
        adaper.setRecyclerListListener(this);
        mainRecyclerView.setAdapter(adaper);
        mainRecyclerView.setOnScrollListener(recyclerScrollListener);
    }
    
    /*---------省略部分代码--------------*/
    
    /**
     * 加载更多的判断和触发
     * */
    private RecyclerView.OnScrollListener recyclerScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            int visibleItemCount    = mainRecyclerView.getLayoutManager().getChildCount();
            int totalItemCount      = mainRecyclerView.getLayoutManager().getItemCount();
            int pastVisibleItems    = ((GridLayoutManager) mainRecyclerView.getLayoutManager())
                    .findFirstVisibleItemPosition();

            if((visibleItemCount + pastVisibleItems) >= totalItemCount && !moviePresenter.isLoading()
                    && !moviePresenter.isLast()) {
                moviePresenter.loadMore();
            }
        }
    };

Presenter

处理网络请求以及数据分发

package com.jwenfeng.moviemvp.presenters;

import android.util.Log;

import com.jwenfeng.moviemvp.model.Movies;
import com.jwenfeng.moviemvp.view.MovieView;

import java.util.List;

import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.listener.FindListener;

/**
 * 当前类注释:
 * 项目名:MovieMVP
 * 包名:com.jwenfeng.moviemvp.presenters
 * 作者:jinwenfeng on 16/4/23 16:38
 * 邮箱:823546371@qq.com
 * QQ: 823546371
 * 公司:南京穆尊信息科技有限公司
 * © 2016 jinwenfeng
 * ©版权所有,未经允许不得传播
 */
public class MoviePresenter extends Presenter {

    private MovieView movieView;

    private int limit = 8;        // 每页的数据是8条
    private int curPage = 0;        // 当前页的编号,从0开始

    private boolean isLoading = false;
    private boolean isLast = false;

    public void attachView(MovieView movieView) {
        this.movieView = movieView;
    }

    /**
     * 获取数据
     * */
    public void getData() {
        BmobQuery<Movies> query = new BmobQuery<>();
        query.setSkip(curPage * limit);
        query.setLimit(limit);
        query.findObjects(movieView.getContext(), new FindListener<Movies>() {
            @Override
            public void onSuccess(List<Movies> list) {
                if (list.size() > 0) {
                    if (movieView.isTheListEmpty()) {
                        movieView.hideLoading();
                    }
                    if (movieView.isSwipeRefresh()) {
                        movieView.showMovies(list);
                        movieView.hideSwipeRefresh();
                    } else {
                        Log.e("MoviePresenter",curPage+"----"+list.size());
                        movieView.appendMovies(list);
                    }
                    curPage++;
                    isLast = false;
                    isLoading = false;
                } else {
                    isLast = true;
                    isLoading = false;
                    movieView.showToast("没有更多数据了");
                }
            }

            @Override
            public void onError(int i, String s) {
                Log.e("MoviePresenter", i + "---" + s);
                movieView.showToast("查询失败:" + s);
            }
        });
    }

    /**
     * 加载更多
     * */
    public void loadMore() {
        if (!isLast && !isLoading){
            isLoading = true;
            getData();
        }
    }

    /**
     * 刷新
     * */
    public void refresh() {
        curPage = 0;
        movieView.showSwipeRefresh();
        isLoading = true;
        getData();
    }

    @Override
    public void start() {
        if (movieView.isTheListEmpty()) {
            movieView.showLoading();
            isLoading = true;
            getData();
        }
    }

    @Override
    public void stop() {

    }

    public boolean isLoading() {
        return isLoading;
    }

    public boolean isLast() {
        return isLast;
    }
}
 

Model

最后的Model就不贴了,就是一个bean

模式没有固定的,适合自己的就是最好的,欢迎关注,不足之处请指教,如果有兴趣可以参考放在GitHub上的源码

github地址:https://github.com/823546371/MovieMVP

本文地址:http://www.jianshu.com/p/6c883af5cabb

尊重原创,转载请注明:From 晓峰残月(http://jwenfeng.com) 侵权必究!

上一篇 下一篇

猜你喜欢

热点阅读