MVP架构由浅入深篇三(终极版)

MVP架构由浅入深篇三(终极版)

前言:在从基础版MVP架构优化成进阶版MVP架构的过程中,几乎每个单元都做了很大优化并封装到了base层,但是唯独Model层没什么变化。所以,终极版MVP架构的优化主要就是对Model层的优化。


一、Model单独封装,集中管理

先看一下整体的架构模型先:

Model层相比其他单元来说其功能就是通过回调接口向上层返回数据。再就是MVP的理念是让业务逻辑互相独立,这就导致每个的网络请求也被独立成了单个Model,这种方式在实际开发中就会出现一些问题:

  1. 无法对所有Model统一管理。
  2. 每个Model对外提供的获取数据方法有差异,没有统一规范。
  3. 代码冗余高,网络数据请求除URL和参数外其他大概都一样的。
  4. 对已存在的Model管理困难,不能直观的统计已存在的Model。

所以我们更希望Model层是一个庞大且独立单一模块,请求方式规范化,管理Model更加直观。

从上面的框架图可以看出,Presenter 请求数据不再直接调用具体的Model对象,统一以 DataModel 类作为数据请求层的入口,以常量类 Token 区别具体请求。 DataModel会根据Token的不同拉取底层对应的具体Model。

二、代码实现

从上面的流程如图可知:

  • DataModel: 数据层顶级入口,项目中所有数据都由该类流入和流出,负责分发所有的请求数据。
  • Token:数据请求标识类,定义了项目中所有的数据请求。
  • BaseModel:所有Model的顶级父类,负责对外提供数据请求标准,对内为所有Model提供请求的底层支持。

1.BaseModel实现

BaseModel中定义了对外的请求数据规则,包括设置参数的方法和设置Callback的方法,还可以定义一些通用的数据请求方法,比如说网络请求的Get和Post方法。

package com.example.mvpapplication.basemodel;

import com.example.mvpapplication.base.Callback;

import java.util.Map;

public abstract class BaseModel <T>{
    //数据请求参数
    protected String[] params;

    /**
     * 设置数据请求参数
     * @param args
     * @return
     */
    public BaseModel setParams(String...args){
        this.params = args;
        return this;
    }

    /**
     * 抽象方法,具体实现由子类实现
     * @param callback
     */
    public abstract void execute(Callback<T> callback);

    protected void requestGetAPI(String url,Callback<T> callback){
        //这里写get API方法请求网络数据
    }
    protected void requestPostAPI(String url, Map params,Callback<T> callback){
        //这里写post API方法请求网络数据
    }
}

2.DataModel实现--(model-one)

package com.example.mvpapplication.basemodel;

import android.os.Handler;

import com.example.mvpapplication.base.Callback;

public class UserDataModel extends BaseModel<String> {
    @Override
    public void execute(final Callback<String> callback) {
        //模拟网络请求
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                switch (params[0]){
                    case "nomal":
                        callback.onSuccess("根据参数"+params[0]+"的请求网络数据成功");
                        break;
                    case "failure":
                        callback.onFailure("失败");
                        break;
                    case "error":
                        callback.onError();
                        break;
                }
                callback.onComplete();
            }
        },2000);
    }
}

3.DataModel实现

DataModel的功能主要是根据token管理每个model,所以采用反射机制来得到实例,其中token就是“包名+类名”。

package com.example.mvpapplication.basemodel;

public class DataModel {
    
    public static BaseModel request(String token){
        BaseModel model = null;
        try {
            model = (BaseModel) Class.forName(token).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return model;
    }
}

4.Token的实现

package com.example.mvpapplication.basemodel;

public class Token {
    // 包名 com.example.mvpapplication.basemodel.
    private static final String PACKAGE_NAME = "com.example.mvpapplication.basemodel.";

    // 具体Model
    public static final String API_USER_DATA = PACKAGE_NAME + "UserDataModel";
}

 5.如何使用?

package com.example.mvpapplication;

import com.example.mvpapplication.base.BasePresenter;
import com.example.mvpapplication.basemodel.DataModel;
import com.example.mvpapplication.basemodel.Token;

/**
 * 这里相当于中介的作用
 */
public class MvpPresenter extends BasePresenter<MvpView> {

    //因为中介要和雇主打交道,所以要声明MvpView
    private MvpView mView;

    public MvpPresenter(){}

    public MvpPresenter(MvpView view){
        this.mView = view;
    }

    /**
     * 相当于帮我找房子--请求数据
     * @param param
     */
    public void getData(String param){
        if (!isViewAttached())
            return;
        //显示正在加载进度条
        getView().showLoading();

        //调用新版Model请求数据
        DataModel.request(Token.API_USER_DATA).setParams("user").execute(new MvpCallback() {
            @Override
            public void onSuccess(String data) {
                //调用view接口显示数据
                if (isViewAttached()){
                    getView().showData(data);
                }
            }

            @Override
            public void onFailure(String msg) {
                if (isViewAttached()){
                    getView().showToast(msg);
                }
            }

            @Override
            public void onError() {
                if (isViewAttached()){
                    getView().showErr();
                }
            }

            @Override
            public void onComplete() {
                if (isViewAttached()){
                    getView().hideLoading();
                }
            }
        });
    }
}

总结

经过优化的Model层很好的统一化了请求方法规范,利用BaseModel不仅有效的减少了数据请求的冗余代码,最关键的还是得到了将所有Model的集中控制权。

如果要新添加一个model:

  1. 新建一个Model并继承BaseModel,完成具体的数据请求。
  2. 在Token中添加对用的Model包名+类名。

至此,终极版MVP框架已经分析完了,从最初的基础版-->进阶版-->终极版,我们进行了一步一步的优化,使代码复用率更高,逻辑层次更加清晰,漏洞越来越少,框架越来越强大。但是MVP之路还没有结束,根据具体的项目需求,可以对框架进行有针对性地修改,使之更加匹配自己的项目需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值