Android之通用MVP模式框架

本文介绍了Android开发中通用的MVP模式框架的使用,强调其带来的代码清晰性、低耦合度和易于扩展的优点。文章详细阐述了BaseModelInter、BaseViewInter、BasePresenter的接口设计以及内存溢出的处理方法。通过FirstActivity的例子展示了如何在实际项目中应用此框架,包括BaseActivity、FirstActivity、FirstActivityPresenter和FirstActivityModelImp的交互过程,以此说明该框架的灵活性和可扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android之通用MVP模式框架

在最近的学习中,我写代码都一直在使用通用的MVP模式框架,在使用的过程中,最让我感触非常深的是,整个代码的层次感非常清晰,耦合度非常低,扩展非常方便,以及能很好的处理Presenter和View直接内存溢出情况。如果你在写代码,我非常建议你使用这种框架下,下面请跟着我的思路走吧。

1、先看以下的构架:

这里写图片描述

在这里你将看到model层下的BaseModelInter、presenter层下的BasePresenter、view层下的BaseViewInter。下面我们来看看这两个接口,以及一个抽象类的代码。

BaseModelInter.java

public interface BaseModelInter {
}

BaseViewInter.java

public interface BaseViewInter {
}

BasePresenter.java

public abstract class BasePresenter<T extends BaseViewInter, M extends BaseModelInter> {
    private WeakReference<T> weakReference;
    protected M model;
    public void attach(T t) {
        weakReference = new WeakReference<>(t);
        model = getModel();
    }

    public void deAttach() {
        if (weakReference != null) {
            weakReference.clear();
            weakReference = null;
        }
    }

    public boolean isViewAttached() {
        return weakReference != null && weakReference.get() != null;
    }

    public T getView() {
        if (weakReference != null) {
            return weakReference.get();
        }
        return null;
    }
    protected abstract M getModel();
}

然后你会发现,我艹,怎么那两个接口中怎么什么都没写,你也把和这个代码贴上来了,是不是找干啊?没错,我就是要贴上来,就是不怕你干我!好了,开个小玩笑,回归正题,其实这样定义两个接口主要是为了扩展子接口,扩展子功能的,因为我们的主题是为了打造通用的框架,那它到底能扩展什么呢?接着往下看你就知道了。然后再看这个抽象类BasePresenter,这个抽象类,最关键的就是解决Presenter和view直接在长时间请求网络数据的情况下,为了防止内存溢出而设计的,我们通过一个虚引用就能很好的解决这个问题了。然后attach方法主要是将需要与具体的presenter类做绑定的view关联起来,并且将对应的model也绑定起来。而这个view类刚好是属于BaseViewInter下的子类。deAttach方法主要是当view向presenter请求数据时,由于网络请求时间过长,而view直接销毁了,而presenter没有即使返回数据,则deAttach就会把对应的view取消关联。isViewAttached方法判断view与presente是否关联,getView是返回一个绑定好的view对象,getModel方法则是让具体的presenter子类去创建具体的model对象。

2.下面看一个具体的实例:

FirstActiviy界面一需要向他对应的presenter层的FirstActivityPresenter请求数据AAAA,然后presenter去找与其具体对应的model层FirstActivityModelImp去拿数据。然后将数据返回给FirstActivity。

框架结构如下:

这里写图片描述

首先先看看BaseActivity.java和FirstActivity.java的代码:

BaseActivity.java

public abstract class BaseActivity<T extends BasePresenter,V extends BaseViewInter> extends AppCompatActivity {
    protected T presenter;//③
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);//④
        presenter = getPresenter();//⑤
        presenter.attach((V)this);//⑦
    }

    protected abstract T getPresenter();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.deAttach();
    }
}

FirstActivity.java

public class FirstActivity extends BaseActivity<FirstActivityPresenter,FirstActivity> implements FirstActivityViewInter {

    private TextView mTv; //①
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);//②
        setContentView(R.layout.first_activity);//⑧
        mTv = (TextView)findViewById(R.id.mTv);//⑨
        presenter.load("我是第一个view,我要获取数据,请presenter为我拿回一个字符串AAAA");//10
    }

    @Override
    public void doSth(String data) {
        Log.i("IT_Real", "doSth: 我获取了字符串" + data);
        mTv.setText("我拿到的数据是:" + data);
    }

    @Override
    protected FirstActivityPresenter getPresenter() {//⑥
        return new FirstActivityPresenter();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

从上面代码看firstActivity继承了BaseActivity类。大家看看上面的执行顺序吧。从上面的10个顺序中,大家应该能理解吧, FirstActivity类首先开始执行,然后第6步将一个具体的FirstActivityPresenter返回给了父类的presenter。然后第7步是将FirstActivity和presenter进行关联。最后执行第10步向具体的FirstActivityPresenter请求数据AAAA。

FirstActivityPresenter.java

public class FirstActivityPresenter extends BasePresenter<FirstActivity,FirstActivityModelImp> {

    @Override
    protected FirstActivityModelImp getModel() {
        return new FirstActivityModelImp();
    }

    public void load(String request){
        model.dealSth(request,new OnSendStrListener() {
            @Override
            public void sendAAAA(String aaaa) {
                getView().doSth(aaaa);
            }
        });
    }
}

load方法主要是向model去拿具体的数据,然后将具体的数据返回给view层。这个类继承了BasePresenter类,可以看到,我们可以通过getView很好的拿到关联的FirstActivity类的具体实例,也能通过model拿到FirstActivityModelImp的具体实例。这样FirstActivityPresenter不持有FirstActivity的引用,就避免了内存溢出的发生。

FirstActivityViewInter.java

public interface FirstActivityViewInter extends BaseViewInter{
    void doSth(String data);
}

上面这个接口中提供的就是所有FirstActivity中需要实现的功能,包括以后需要具体扩展FirstActivity中功能等,非常方便。

最后看看Model层中的类

FirstActivityModelInter.java

/**
* 所有FirstModelImp中需要实现的数据操作功能,以后需要操作上面功能,直接在这个接口中添加即可,
* 扩展性好。
*/
public interface FirstActivityModelInter extends BaseModelInter{
    void dealSth(String request,OnSendStrListener listener);
}

OnsendStrListener.java

/**
* 具体要处理数据的回调接口,因为View需要一个字符串AAAA,所以就给他提供一个方法发回一个字符串
* 具体的功能自己定义即可,这里不统一,根据实际需求
*/
public interface OnSendStrListener {
    void sendAAAA(String aaaa);
}

FIrstActiviyModelImp.java

public class FirstActivityModelImp implements FirstActivityModelInter {
    /**
    * 将具体的数据返回给FirstActivityPresenter,实现具体的数据操作功能。
    */
    @Override
    public void dealSth(String request, OnSendStrListener listener) {
        if (request.equals("我是第一个view,我要获取数据,请presenter为我拿回一个字符串AAAA")){
            Log.i("IT_Real", "dealSth: presenter需要一个AAAA数据,我要返回一个AAAA数据");
            //接口回调该方法,就是将AAAA发回给presenter
            listener.sendAAAA("AAAA");
        }
    }
}

通过上面的具体实现,在以后的项目中,我们可以扩展非常方便,这里我只实例了一个界面需要处理的功能,以及请求上面数据等。如果说以后你需要扩展多个界面,就像我一样,在view包下的activity下新建一个SecondActiviy类即可,然后该类继承BaseActivity,创建一个新的SecondViewInter (需要继承BaseViewInter),将所有功能写入到其中,然后让SecondActivity类去实现即可,next创建对应的SecondPresenter,去继承BasePresenter。处理一些事情即可,最后同样写一个SecondModelImp类,去实现SecondModleInter接口(需要继承BaseModelInter)中的具体功能即可。。。这样一来,我们的层次会非常清晰,然后扩展功能也非常方便,耦合也非常低,源代码上传一下,希望大家也可以养成这样的好习惯,建议使用这种模式写代码,对以后的工作会有很大的帮助哦。

源代码

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值