工作生活

Android MVP框架搭建

2019-06-30  本文已影响0人  Chenyangqi

MVP框架搭建·源码
通过本文记录一下学习MVP三层架构的思想,并实现一个基础的MVP项目架构搭建过程,通过MVC架构设计一文了解到MVC存在内存泄漏的缺陷,而MVP通过弱应用可以很好的解决内存泄漏这个问题
本文通过用户登录案例实现MVP框架的搭建

image.png
MVP相对于MVC的区别在于,增加了Presenter协议层,通过Presenter协议层解耦了View层和Model层,MVP架构大致分为以下三种类型

具体选用那种看团队最终框架如何定义。

基类封装

通过弱引用避免了P层对V层的持有,当Activity finish的时候能够完全腾出内存占用

public abstract class BaseModel<P extends BasePresenter, CONTRACT> {
    protected P p;
    //业务结束,通过Presenter调用契约、合同(接口中的方法)void responseResult(T t)

    public BaseModel(P p) {
        this.p = p;
    }

    public abstract CONTRACT getContract();
}

public abstract class BaseView<P extends BasePresenter, CONTRACT> extends Activity {
    protected P p;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //弱引用
        p = getPresenter();
        //绑定
        p.bindView(this);
    }

    //让P层做什么需求
    public abstract CONTRACT getContract();

    //从子类中获取具体的契约
    public abstract P getPresenter();

    //如果Presenter层出现异常,需要告知View层

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解除绑定
        p.unBindView();
    }
}

public abstract class BasePresenter<V extends BaseView, M extends BaseModel, CONTRACT> {

    protected M m;
    private WeakReference<V> vWeakReference;

    public BasePresenter() {
        m = getModel();
    }

    public void bindView(V v) {
        vWeakReference = new WeakReference<>(v);
    }

    public void unBindView() {
        if (vWeakReference != null) {
            vWeakReference.clear();
            vWeakReference = null;
            System.gc();
        }
    }

    //获取View,P--V
    public V getView() {
        if (vWeakReference != null) {
            return vWeakReference.get();
        }
        return null;
    }

    //获取子类具体契约(Model层和View层协商的共同业务)
    public abstract CONTRACT getContract();

    public abstract M getModel();
}
登录逻辑的实现
public interface LoginContract {
    interface Model {
        void executeLogin(String name, String pwd) throws Exception;
    }

    interface View<T extends BaseEntity> {
        //真实项目中们,请求结果往往是JavaBean
        void handlerResult(T t);
    }

    interface Presenter<T extends BaseEntity> {
        //登录请求(接收到View层的指令,可以自己做,也可以让Model层去执行)
        void requestLogin(String name, String pwd);

        //结果响应(接收到Model层处理的结果,通知View层刷新)
        void responseResult(T t);
    }
}
public class LoginModel extends BaseModel<LoginPresenter, LoginContract.Model> {

    public LoginModel(LoginPresenter loginPresenter) {
        super(loginPresenter);
    }

    @Override
    public LoginContract.Model getContract() {
        return new LoginContract.Model() {
            @Override
            public void executeLogin(String name, String pwd) throws Exception {
                //模拟网络请求
                if ("zhangsan".equalsIgnoreCase(name) && "123456".equalsIgnoreCase(pwd)) {
                    p.getContract().responseResult(new UserInfo("腾讯", "马化腾"));
                } else {
                    p.getContract().responseResult(null);
                }
            }
        };
    }
}
public class LoginPresenter extends BasePresenter<LoginActivity, LoginModel,
        LoginContract.Presenter> {
    @Override
    public LoginContract.Presenter getContract() {
        //既要履行View给他的需求,又要分配工作给Model去完成这个需求
        return new LoginContract.Presenter<UserInfo>() {
            @Override
            public void requestLogin(String name, String pwd) {
                //P层三种风格
                try {
                    //第一种:P层不做事情,只做转发,交给M层做
                    m.getContract().executeLogin(name, pwd);

                    //第二种:让功能模块做(Library:下载,请求,图片加载等功能模块)
                    //HttpEngine httpEngine = new HttpEngine<>(LoginPresenter.this);
                    //httpEngine.post(name, pwd);

                    //第三种:P层自己处理(google MVP samples就是这种)
                    /*if ("zhangsan".equalsIgnoreCase(name) && "123456".equalsIgnoreCase(pwd)) {
                        responseResult(new UserInfo("腾讯", "马化腾"));
                    } else {
                        responseResult(null);
                    }*/

                    //内存泄漏测试
                    /*new Thread(new Runnable() {
                        @Override
                        public void run() {
                            SystemClock.sleep(60000);
                        }
                    }).start();*/
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void responseResult(UserInfo userInfo) {
                //不管谁完成
                getView().getContract().handlerResult(userInfo);
            }
        };
    }

    @Override
    public LoginModel getModel() {
        return new LoginModel(this);
    }
}

最终LoginActivity实现登录逻辑的代码如下,代码简洁,易于后期维护

public class LoginActivity extends BaseView<LoginPresenter, LoginContract.View> {
    private EditText nameEt;
    private EditText pwdEt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        nameEt = findViewById(R.id.et_account);
        pwdEt = findViewById(R.id.et_password);
    }

    public void doLoginAction(View view) {
        String name = nameEt.getText().toString();
        String pwd = pwdEt.getText().toString();
        p.getContract().requestLogin(name, pwd);
    }

    @Override
    public LoginContract.View getContract() {
        return new LoginContract.View<UserInfo>() {
            @Override
            public void handlerResult(UserInfo userInfo) {
                if (userInfo != null) {
                    Toast.makeText(LoginActivity.this, userInfo.toString(), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(LoginActivity.this, "登录失败!", Toast.LENGTH_SHORT).show();
                }
            }
        };
    }

    @Override
    public LoginPresenter getPresenter() {
        return new LoginPresenter();
    }
}

MVP框架搭建·源码

上一篇 下一篇

猜你喜欢

热点阅读