Android:浅谈自己理解的MVP,并搭建MVP大致框架

浅谈: 

M:Model,就是entity实体

V:View,就是activity,提供修改UI界面方法给P调用

P:Presenter,将activity界面获取到的数据拿过来处理,处理完了调用activity提供的方法更新界面UI

我们开发的时候,跟界面显示有关的才在Activity中做,否则就在Presenter中做,Presenter做网络请求,把拿到的Model传给Activity做数据展示。

MVP模式下,我们想要的效果是这样:在Activity中直接通过getP()得到这个Activity对应的Presenter对象,然后调用Presenter里面的方法。然后在Presenter中可以通过getV()直接得到这个Activity。

这边没有封装Model层。

举个登录的栗子:

 LoginActivity中提供登录成功和登录失败的不同状态显示,然后调用getP().login(number,pwd);去登陆。

这个login(String,String)登录方法是在Presenter里面定义的,他在登录里面请求后台,得到响应,然后调用getV().loginSuccess(User user)或者getV().loginFail(String errorMsg)来在Activity中显示成功或失败的效果。


搭建:

我尽量简化来理解。先来看一下主要创建的基类和base类,基类放都要共同实现的方法,base放每个activity都要用到的方法:

  其中还有BaseFragment类似BaseActivity的封装法,先不举例,避免混淆,具体看demo。


先来写mvp的基类:

1、首先IModel可以提取实体类共同的方法来写,比如error_code、msg之类的,这个看服务器给你什么数据。我这里没有,所以这个Imodel是空的。

2、然后IPresenter:

public interface IPresenter<V extends IView> {
    /**
     *  关联P与V(绑定,VIEW销毁适合解绑)
     */
    void attachView(V view);

    /**
     *  取消关联P与V(防止内存泄漏)
     */
    void detachView();

    /**
     *  获取view
     */
    V getV();

    /**
     * 是否已经绑定了view
     */
    boolean isAttachedV();

}

3、IView:

public interface IView<P extends IPresenter> {

    /**
     * @return 布局id
     */
    int getLayoutId() ;

    void initView();

    void initData();

    void initListener();

    P newP();

    void error();
}

然后是实现基类的base类:

1、BaseModel,同样,啥都没写。

2、BasePresenter:

import com.xaehu.myapplication.mvp.IPresenter;
import java.lang.ref.WeakReference;

public class BasePresenter<V extends BaseActivity> implements IPresenter<V> {

    private WeakReference<V> v;

    @Override
    public void attachView(V view) {
        v = new WeakReference<>(view);
    }

    @Override
    public void detachView() {
        if (v.get() != null) {
            v.clear();
        }
        v = null;
    }

    @Override
    public V getV() {
        if(v == null || v.get() == null){
            return null;
        }
        return v.get();
    }

    @Override
    public boolean isAttachedV() {
        return v != null && v.get() != null;
    }

}

3、BaseActivity:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.widget.Toast;

import com.xaehu.myapplication.mvp.IView;

import java.util.Objects;

public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IView<P> {

    private P p;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        initView();
        initData();
        initListener();
        initSetting();
    }

    protected void initSetting(){
        //左侧添加一个默认的返回图标
        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(hasBackBtn());
        //设置返回键可用
        getSupportActionBar().setHomeButtonEnabled(hasBackBtn());
    }

    /**
     * @return 是否有返回按钮
     */
    protected boolean hasBackBtn(){
        return false;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //Toolbar的事件---返回
        if(item.getItemId() == android.R.id.home){
            if(hasBackBtn()){
                finish();
            }
        }
        return super.onOptionsItemSelected(item);
    }

    public void showToast(String msg){
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    public void showLongToast(String msg){
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    /**
     * 获取Presenter
     */
    public P getP(){
        if(p == null){
            p = newP();
        }
        if(p != null){
            if(!p.isAttachedV()){
                p.attachView(this);
            }
        }
        return p;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(getP()!=null){
            getP().detachView();
        }
        p = null;
    }

}

这样,就搭建完成了,然后用法举例:

比如登录的activity:LoginActivity:

public class LoginActivity extends BaseActivity<LoginPresenter> implements View.OnClickListener {

    private EditText etName;
    private EditText etPwd;
    private Button btnLogin;

    @Override
    public int getLayoutId() {
        return R.layout.acticity_login;
    }

    @Override
    public void initView() {
        etName = findViewById(R.id.et_name);
        etPwd = findViewById(R.id.et_pwd);
        btnLogin = findViewById(R.id.btn_login);
    }

    @Override
    public void initData() {

    }

    @Override
    public void initListener() {
        btnLogin.setOnClickListener(this);
    }

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

    @Override
    public void error() {

    }

    @Override
    public void onClick(View v) {
        getP().login(etName.getText().toString(),etPwd.getText().toString());
    }

    @Override
    protected boolean hasBackBtn() {
        return true;
    }

    //登录成功做界面跳转,参数应该是实体,这里是为了测试用
    public void loginSuccess(String name,String pwd){
        Intent intent = new Intent(this,MainActivity.class);
        intent.putExtra("name",name);
        intent.putExtra("pwd",pwd);
        startActivity(intent);
    }

    public void loginFail(){
        showToast("用户名或密码错误");
    }

}

 对应的P:

public class LoginPresenter extends BasePresenter<LoginActivity> {

    public void login(String name,String pwd){
        if(name.isEmpty() || pwd.isEmpty()){
            getV().showToast("用户名和密码都不能为空");
        }else{
             TODO:   请求

             TODO:  模拟请求
            if(!name.equals("1")){
                getV().loginSuccess(name,pwd);
            }else{
                getV().loginFail();
            }
        }
    }
}

最后附上demo地址:GitHub

下一篇:封装Retrofit2+Rxjava2的MVP框架结构

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值