深入浅出Android MVP

项目地址

java:https://github.com/zhangtiansimple/androidmvp_java

kotlin:https://github.com/zhangtiansimple/androidmvp_kotlin

 

本文将通过一个例子的不断优化,让同学们可以体会到MVP的优势。

现在有这样一个需求,在登录页上有一个登录按钮,点击就触发登录逻辑。

最普通的写法会怎么写呢?在当前Activity下

loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.print("user login");
            }
        });

这样看起来很简单,但是当项目规模较大需要多人协作开发的话,如此写法使得各个模块之间的耦合很深,协同开发难度很大,使用MVP可以把不同的模块解藕出去,Module模块负责数据等功能,View层的UI部分只关心UI实现,最后通过Presenter将其关联起来,架构清晰,协作开发效率高。

现在开始使用MVP来进行优化

第一步,添加UserModule、UserView、UserPresenter

UserModule类里添加login方法

public class UserModule {
    public void login(String userName, String password) {
        System.out.print("user login");
    }
}

UserView接口

public interface UserView {
    void onLoginResult(String result);
}

UserPresenter类 持有module的引用 持有View的引用

public class UserPresenter {
    private UserModule userModule;
    private UserView userView;

    public UserPresenter(UserView userView) {
        this.userModule = new UserModule();
        this.userView = userView;
    }

    public void login(String userName, String password) {
        userModule.login(userName, password);
        if (userView != null) {
            userView.onLoginResult("");
        }
    }
}

那么此时,只需要在当前Activity下

UserPresenter userPresenter = new UserPresenter(new UserView() {
    @Override
    public void onLoginResult(String result) {

    }
});
userPresenter.login("", "");

这样一个简单的MVP就写好了,代码虽然变多了,但是结构却更加清晰了,不过这样一个MVP还存在很多问题,接下来大家一起来找茬。

问题一:当我们的网络请求正在进行,这个时候我们退出了Activitiy,然后UI层引用还在,还会回调,其实没有必要了,我们可以直接终止请求。

解决方案:绑定和解绑

在Presenter类里添加绑定和解绑方法

public class UserPresenter {
    private UserModule userModule;
    private UserView userView;

    public UserPresenter() {
        this.userModule = new UserModule();
    }

    public void attachView(UserView userView) {
        this.userView = userView;
    }

    public void detachView() {
        this.userView = null;
    }

    public void login(String userName, String password) {
        userModule.login(userName, password);
        if (userView != null) {
            userView.onLoginResult("");
        }
    }
}

然后修改Activity里的代码,并且在onDestory解绑

userPresenter = new UserPresenter();
    userPresenter.attachView(new UserView() {
        @Override
        public void onLoginResult(String result) {

        }
    });
    userPresenter.login("", "");
@Override
protected void onDestroy() {
    super.onDestroy();
    if (userPresenter != null) {
        userPresenter.detachView();
    }
}

这样修改之后,问题一解决了,但是细心的同学肯定会发现这样又会引出一个问题

问题二:一个类还好,如果多个类,那么会反复定义绑定和解绑

解决方案:将绑定和解绑抽象

我们添加一个抽象类来解决这个问题

public abstract class BasePresenter<T extends BaseView> {

    private T view;

    public void attachView(T view) {
        this.view = view;
    }

    public void detachView() {
        this.view = null;
    }

    public T getView() {
        return view;
    }
}

添加这个抽象作为Presenter的父类后,虽然解决了反复定义写重复代码的问题,但是又会引出一个问题

问题三:随着Activity、Fragment数量增加,需要反复的绑定和解除绑定,这个操作属于代码冗余

解决方法:Activity的抽象 + 泛型设计

添加BaseActivity

public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends AppCompatActivity {

    private P presenter;
    private V view;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (presenter == null) {
            presenter = createPresenter();
        }

        if (view == null) {
            view = createView();
        }

        if (presenter != null && view != null) {
            presenter.attachView(view);
        }
    }

    public abstract P createPresenter();

    public abstract V createView();

    public P getPresenter() {
        return presenter;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter != null && view != null) {
            presenter.detachView();
        }
    }
}

Fragment和ViewGroup的原理类似,这里就不添加了,下面是几个类的完整代码

Module

public class UserModule {

    public void login(String userName, String password) {
        System.out.print("user login");
    }
}

View

public interface BaseView {
}
public interface UserView extends BaseView{
    void onLoginResult(String result);
}

Presenter

public abstract class BasePresenter<T extends BaseView> {

    private T view;

    public void attachView(T view) {
        this.view = view;
    }

    public void detachView() {
        this.view = null;
    }

    public T getView() {
        return view;
    }
}
public class UserPresenter extends BasePresenter<UserView> {
    private UserModule userModule;

    public UserPresenter() {
        this.userModule = new UserModule();
    }

    public void login(String userName, String password) {
        userModule.login(userName, password);
        if (getView() != null) {
            getView().onLoginResult("");
        }
    }
}

Activity(BaseActivity在问题三那里)

public class MainActivity extends BaseActivity<UserView, UserPresenter> implements UserView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getPresenter().login("", "");
    }

    @Override
    public UserPresenter createPresenter() {
        return new UserPresenter();
    }

    @Override
    public UserView createView() {
        return this;
    }

    @Override
    public void onLoginResult(String result) {

    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值