博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android中的MVP架构
阅读量:4988 次
发布时间:2019-06-12

本文共 6745 字,大约阅读时间需要 22 分钟。

Android应用的MVC架构,Activity往往充当了View和Control双重角色,造成代码耦合性较强。怎样将View和Control解耦呢,可以使用MVP架构(Model、Control、Prestener)将Activity的View和Control彻底分离,不说废话了直接上代码吧!

github: 

 

以Activity为例,Fragment的原理相同:

View:我们将Activity看作一个单纯的View

package com.allin.android.activity;import com.allin.android.presenter.BasePrestener;import android.app.Activity;import android.os.Bundle;/** * MVP架构中Activity的基类,主要用于与Prestener建立关联并管理生命周期 * @author Allin * 2015.11.24 * @param 
BaseActivity子类需继承的View接口,该接口声明了Activity的各种视图操作逻辑, MVP中的V * @param

BasePrestener子类, MVP中的P */public abstract class BaseActivity

> extends Activity { protected P mPrestener; //持有一个Prestener对象的引用,用来调用Prestener中的数据逻辑 @SuppressWarnings("unchecked") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPrestener = createPrestener(); mPrestener.attachView((V)this); } @Override protected void onDestroy() { super.onDestroy(); mPrestener.detachView(); } protected abstract P createPrestener(); //mPrestener对象延迟到子类生产 }

Prestener:中介者用来处理数据逻辑和View中视图逻辑的流程控制

package com.allin.android.presenter;import java.lang.ref.Reference;import java.lang.ref.WeakReference;/** * MVP架构中Prestener的基类,主要用于与View建立关联并管理生命周期 * @author Allin * 2015.11.24 * @param 
View接口 */public abstract class BasePrestener
{ protected Reference
mViewRef; //持有一个V的引用,用来调用Activity或Fragment中的视图逻辑 public void attachView(V view){ mViewRef = new WeakReference
(view); //此处使用弱引用,防止因Activity或Fragment异常关闭造成内存泄露 } protected V getView(){ return mViewRef.get(); } public boolean isViewAttached(){ return mViewRef != null && mViewRef.get() != null; } public void detachView(){ if(mViewRef != null){ mViewRef.clear(); mViewRef = null; } } }

至此,V和C已经完全解耦。

为了避免Prestener臃肿,我们可以将具体逻辑进一步分离,以联网Api为例:

package com.allin.android.api;import java.util.Map;/**Api基类 * @author Allin * 2015.11.24 */class BaseApi {    /**     * http get请求     * @param url     * @param params     * @param callback 将网络获取的数据回调给调用者     */    public void httpGet(final String url, final Map
params, final ApiCallback callback){ // TODO Auto-generated method stub } /** * http post请求 * @param url * @param params * @param callback 将网络获取的数据回调给调用者 */ public void httpPost(final String url, final Map
params, final ApiCallback callback){ // TODO Auto-generated method stub }}

Api回调接口:

package com.allin.android.api;/** * ApiCallback * @author Allin * 2015.11.24 */public interface ApiCallback {    /**     * 网络请求成功的回调     * @param result     */    
void onSucceed(T result); /** * 网络请求失败的回调 * @param msg */ void onFailed(String msg);}

用法举栗,写一个Activity包含三个功能:创建长度为length的无序数组用ListView展示出来、排序并刷新ListView、统计有多少项的值为value

首先写一个ViewListener声明Activity里面的方法:

package com.allin.android.listener;/** * MVPViewListener * @author Allin * 2015.11.24 */public interface MVPViewListener extends BaseViewListener{        /**     * 创建无序数组并在列表显示     * @param array     */    void showList(int[] array);        /**     * 排序然后刷新列表     */    void sort();        /**     * 统计有多少项的值为value     * @param value     */    void count(int value);}

然后是Activity和Prestener的交互,先看Activity

package com.allin.android.activity;import com.allin.android.adapter.MVPAdapter;import com.allin.android.allin.R;import com.allin.android.listener.MVPViewListener;import com.allin.android.presenter.MVPPrestener;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.EditText;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;/** * MVPActivity * @author Allin * 2015.11.24 */public class MVPActivity extends BaseActivity
    implements MVPViewListener, OnClickListener{
private ListView mListView; private EditText mEditText; private TextView mCountText; private TextView mSortText; private MVPAdapter mAdapter; /** * 父类BasePrestener的抽象函数,必须在子类中实现,用来创建具体的Prestener对象 * Prestener对象及其生命周期全部交给父类管理,子类只需要创建实例就可以了 */ @Override protected MVPPrestener createPrestener() { return new MVPPrestener(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mvp); initView(savedInstanceState); initData(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.count: String edit = mEditText.getText().toString(); int value = Integer.parseInt(edit); count(value); break; case R.id.sort: sort(); break; default: break; } } @Override public void initView(Bundle savedInstanceState) { mListView = (ListView) findViewById(R.id.list); mEditText = (EditText) findViewById(R.id.edit); mCountText = (TextView) findViewById(R.id.count); mSortText = (TextView) findViewById(R.id.sort); mCountText.setOnClickListener(this); mSortText.setOnClickListener(this); } @Override public void initData() { mPrestener.init(); //数据逻辑交给Prestener去处理 } @Override public void showList(int[] array) { mAdapter = new MVPAdapter(array); mListView.setAdapter(mAdapter); } @Override public void sort() { mPrestener.sort(); //数据逻辑交给Prestener去处理 } @Override public void count(int value) { int count = mPrestener.count(value); //数据逻辑交给Prestener去处理 Toast.makeText(this, String.valueOf(count), Toast.LENGTH_SHORT).show(); }}

Prestener

package com.allin.android.presenter;import com.allin.android.algorithms.Sort;import com.allin.android.listener.MVPViewListener;import com.allin.android.util.Factory;/** * MVPPrestener * @author Allin * 2015.11.24 */public class MVPPrestener extends BasePrestener
{ private int[] array; public void init(){ array = Factory.createArray(1000); getView().showList(array); } public void sort(){ Sort.sort(array); getView().showList(array); } public int count(int value){ int count = 0; for (int i = 0; i < array.length; i++) { if(value == array[i]){ count++; } } return count; }}

 视图与数据逻辑分离之后,两边的代码都十分干净清爽,而且方便维护。缺点在于对开发人员的接口设计能力要求比较高

转载于:https://www.cnblogs.com/allin1579/p/5000823.html

你可能感兴趣的文章
MVC详解
查看>>
海洋cms 模板标签手册
查看>>
adt-bundle-windows-x86_32-20140702
查看>>
HTML5小游戏【是男人就下一百层】UI美化版
查看>>
SSH免密登陆
查看>>
java根据图片和文字生成自定义图片
查看>>
《ASP.NET SignalR系列》第五课 在MVC中使用SignalR
查看>>
Catenyms (POJ2337) 字典序最小欧拉路
查看>>
ZT : 优秀程序员的两大要素:懒 + 笨
查看>>
Centos6.5-dnsmasq安装
查看>>
PyCharm+Eclipse共用Anaconda的数据科学环境
查看>>
笔记3 | 通过onWindowAttributesChanged和onSystemUiVisibilityChange监听状态栏页面的隐藏与显示、动态显示与隐藏状态栏...
查看>>
msysgit 上传文件夹,规范化的日常
查看>>
CSS清除浮动
查看>>
Zookeeper之ZKClient的使用
查看>>
WTF小程序之animation
查看>>
那些前端二进制操作API
查看>>
一 、Spring Boot 学习之项目搭建
查看>>
一键部署joomla开源内容管理平台
查看>>
opencv画图
查看>>