一、Google 官方MVP介绍
近期,关于Android开发架构的讨论沸沸扬扬,各大技术平台随处可见关于Android架构的技术文章。MVC、MVP、MVVM等等,就目前的形式来看,MVP模式在Android开发领域界逐渐流行了起来。前段时间,Google也忍耐不住Android MVP架构的火热程度,给广大Android程序员带来了福利,推出了Google官方MVP架构例子。源码见: https://github.com/googlesamples/android-architecture
官方给出了四种MVP架构模式:
1、todo-mvp:MVP基础架构
2、todo-mvp-loaders:基于MVP基础架构,获取数据部分使用了Loaders架构
3、todo-mvp-databinding:基于MVP基础架构,使用了数据绑定组件
4、todo-mvp-clean:基于MVP基础架构,引入Clean架构概念
官方正在进行的MVP架构模式:
1、todo-mvp-contentproviders:基于MVP基础架构,使用了Content Provider
2、todo-mvp-dragger:基于MVP基础架构,使用dragger2依赖注入
3、todo-mvp-rxjava:基于MVP基础架构,使用RxJava解决数据并发
二、MVP架构模式介绍
MVP中的M代表Model,即数据层,V代表View,即界面层,P代表Presenter,负责关联Model和View,把Model层的数据显示到View。
三、MVP架构实践
这里,我从todo-mvp基础架构入手,模仿一下官方MVP源码,跟大家详细介绍一下Google官方MVP架构模式。官方的MVP示例源码展示的是一个简易便签,数据提供者是Sqlite数据库。我的项目里面数据提供者是网络,使用okhttp网络请求框架从服务器获取数据。一起来看看神奇的MVP架构模式是怎样把数据显示到手机界面的吧。
google官方todo-mvp模式架构图(结合todo-mvp源码可以好好感受一下mvp的魅力)
Presente基础接口
public interface BasePresenter { void start(); }
public interface BaseView<T> { void setPresenter(T presenter); }
具体任务的Presener和View接口,Presenter接口里面封装的是数据获取的方法,需要数据提供者具体实现;View里面封装的方法是界面层(Fragment/Activity)要实现的方法。
public interface TaskDetailContract { //http://www.diandidaxue.com:8080/apiServer.do?opcode=getBeauty&pageNum=1&numPerPage=5 interface Presenter extends BasePresenter{ void loadBeauty(int pageIndex, int pageSize); } interface View extends BaseView<Presenter>{ void showProgress(); void hideProgress(); void showBeauty(List<Beauty> beautyList); } }
数据提供者,基于Okhttp请求,我这里使用的鸿洋大神封装好的Okhttp请求库。提供一个接口,将数据共享出去,提供给具体Presenter。
Okhttp封装具体使用方法见:http://blog.csdn.net/lmj623565791/article/details/47911083
数据提供的服务器是我自己搭建的一个阿里云服务器,为了平时开发方便,写了一个数据接口,可以获取大量的美女图片和文字信息,get和post请求都支持,便于开发时候做数据测试。数据接口地址:http://www.diandidaxue.com:8080/apiServer.do?opcode=getBeauty&pageNum=1&numPerPage=50
public class ServerHelper { private DataLoadListener listener; public void getBeautyList(int pageIndex, int pageSize){ String url = "http://www.diandidaxue.com:8080/apiServer.do"; Map<String, String> params = new HashMap<String, String>(); params.put("opcode", "getBeauty"); params.put("pageNum", String.valueOf(pageIndex)); params.put("numPerPage", String.valueOf(pageSize)); OkHttpUtils.post().url(url).params(params).build().execute(new ListBeautyCallBack() { @Override public void onError(Call call, Exception e) { listener.failure(e); } @Override public void onResponse(List<Beauty> response) { listener.success(response); } }); } public interface DataLoadListener{ void failure(Exception e); void success(List<Beauty> beautyList); } public void setListener(DataLoadListener listener) { this.listener = listener; } }
具体Presenter,实现了TaskDetailContract.Presenter和ServerHelper.DataLoadListener接口,关联了TaskDetailContract.View接口,把网络请求到的数据提供给View。
public class TaskPresenter implements TaskDetailContract.Presenter,ServerHelper.DataLoadListener { private TaskDetailContract.View view; private ServerHelper serverHelper; //数据提供者 这里应该封装网络数据请求 public TaskPresenter(TaskDetailContract.View view) { this.view = view; view.setPresenter(this); serverHelper = new ServerHelper(); serverHelper.setListener(this); } /** * 请求网络数据 * @param pageIndex 页码 * @param pageSize 一页显示的数量 */ @Override public void loadBeauty(final int pageIndex, int pageSize) { serverHelper.getBeautyList(pageIndex,pageSize); } @Override public void start() { } @Override public void failure(Exception e) { view.hideProgress(); } @Override public void success(List<Beauty> beautyList) { view.hideProgress(); view.showBeauty(beautyList); } }
public class BeautyFragment extends Fragment implements TaskDetailContract.View, SwipeRefreshLayout.OnRefreshListener { private TaskDetailContract.Presenter presenter; private SwipeRefreshLayout refreshLayout; private RecyclerView recyclerView; private BeautyAdapter adapter; private List<Beauty> beautyList; private int pageIndex = 1; private int pageSize = 8; private boolean isLastPage = false; private int lastVisibleItem = 0; private LinearLayoutManager linearLayoutManager; public static BeautyFragment newInstance(){ return new BeautyFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = new TaskPresenter(this); beautyList = new ArrayList<>(); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_beauty,container,false); recyclerView = (RecyclerView) view.findViewById(R.id.tabRecyler); refreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.tabSwipeRefresh); linearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL,false); //设置下拉刷新 refreshLayout.setColorSchemeColors(R.color.colorAccent); refreshLayout.setOnRefreshListener(this); //第一次进入界面时候加载进度条 refreshLayout.setProgressViewOffset(false, 0, (int) TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources() .getDisplayMetrics())); recyclerView.setLayoutManager(linearLayoutManager); adapter = new BeautyAdapter(beautyList,getActivity()); recyclerView.setAdapter(adapter); presenter.loadBeauty(1,8); recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisibleItem + 1 == adapter.getItemCount()) { Log.i("pageIndex",pageIndex+""); //根据类目网络请求数据 if(!isLastPage){ presenter.loadBeauty(pageIndex,pageSize); } } } }); return view; } @Override public void showProgress() { refreshLayout.setRefreshing(true); } @Override public void hideProgress() { refreshLayout.setRefreshing(false); } @Override public void showBeauty(List<Beauty> list) { ActivityUtils.checkNotNull(list); if(list != null){ if(pageIndex == 1){ beautyList.clear(); beautyList.addAll(list); isLastPage = false; pageIndex ++; }else if(list .size() == pageSize){ beautyList.addAll(list); isLastPage = false; pageIndex ++; }else { beautyList.addAll(list); isLastPage = true; } } adapter.notifyDataSetChanged(); } @Override public void setPresenter(TaskDetailContract.Presenter presenter) { this.presenter = presenter; } @Override public void onRefresh() { pageIndex = 1; presenter.loadBeauty(pageIndex,pageSize); } }
public class BeautyActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_beauty); BeautyFragment fragment = new BeautyFragment(); if(fragment == null){ fragment = BeautyFragment.newInstance(); } ActivityUtils.addFragmentToActivity(getSupportFragmentManager(),fragment,R.id.container); } }
好了,Google 官方MVP架构实践介绍完毕,希望对大家有收获。上述代码是实现MVP架构模式的关键代码,中间还涉及到的ActivityUtils等类都在源码中哦,欢迎大家下载。
源码下载地址:https://github.com/xiaomanzijia/mvp 记得star喔